1. Build Apps using Docker-Compose
Lab assignment for creating a app using docker-compose.
Prerequisites
- Docker
- Docker-Compose
Assignment
- Lets build an app which has a frontend and backend using docker compose.
Create a docker-compose file to save the configuration of the app
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
cat <<EOF> docker-compose.yaml version: "3.9" services: backend: image: backend-app:latest # Replace with your backend image build: context: ./backend dockerfile: Dockerfile # Adjust if your Dockerfile has a different name ports: - "5000:5000" # Exposes the backend on port 5000 environment: - DATABASE_URL=postgres://user:password@db:5432/appdb depends_on: - db # Ensures the database service starts before the backend networks: - app-network frontend: image: frontend-app:latest # Replace with your frontend image build: context: ./frontend dockerfile: Dockerfile # Adjust if your Dockerfile has a different name ports: - "3000:3000" # Exposes the frontend on port 3000 environment: - REACT_APP_API_URL=http://backend:5000 # URL of the backend service depends_on: - backend # Ensures the backend starts before the frontend networks: - app-network db: image: postgres:15 # Replace with your preferred database image/version environment: POSTGRES_USER: user POSTGRES_PASSWORD: password POSTGRES_DB: appdb volumes: - db_data:/var/lib/postgresql/data networks: - app-network networks: app-network: driver: bridge volumes: db_data: EOF
Create Dockerfile for backend container:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cat <<EOF> ./backend/Dockerfile
# Use the official Python image as the base
FROM python:3.11-slim
# Set the working directory in the container
WORKDIR /app
# Copy the application code into the container
COPY . .
# Install Python dependencies
RUN pip install --no-cache-dir -r requirements.txt
# Expose the backend's port
EXPOSE 5000
# Command to run the application
CMD ["python", "app.py"]
EOF
1
2
3
4
cat <<EOF> ./backend/requirements.txt
Flask==2.2.5
psycopg2-binary==2.9.6 # PostgreSQL driver
EOF
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cat <<EOF> ./backend/app.py
from flask import Flask, jsonify
app = Flask(__name__)
@app.route("/")
def home():
return jsonify({"message": "Welcome to the backend API!"})
@app.route("/data")
def data():
return jsonify({"data": "This is some data from the backend!"})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
EOF
- Create a Dockerfile for frontend container.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
cat <<EOF> ./frontend/Dockerfile
# Use the official Node.js image as the base
FROM node:18-alpine
# Set the working directory in the container
WORKDIR /app
# Copy package.json and package-lock.json
COPY package*.json ./
# Install Node.js dependencies
RUN npm install
# Copy the rest of the application code
COPY . .
# Build the React app
RUN npm run build
# Serve the build using a lightweight server
RUN npm install -g serve
# Expose the frontend's port
EXPOSE 3000
# Command to start the frontend
CMD ["serve", "-s", "build", "-l", "3000"]
EOF
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cat <<EOF> ./frontend/package.json
{
"name": "frontend-app",
"version": "1.0.0",
"private": true,
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"axios": "^1.5.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
}
}
EOF
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
cat <<EOF> ./frontend/src/App.js
import React, { useEffect, useState } from "react";
import axios from "axios";
function App() {
const [data, setData] = useState("");
useEffect(() => {
// Call the backend API
axios.get("http://backend:5000/data")
.then(response => setData(response.data.data))
.catch(error => console.error("Error fetching data:", error));
}, []);
return (
<div style={{ textAlign: "center", padding: "50px" }}>
<h1>Frontend React App</h1>
<p>Message from Backend: {data || "Loading..."}</p>
</div>
);
}
export default App;
EOF
1
2
3
4
5
6
7
8
9
10
11
12
13
cat <<EOF> ./frontend/public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Frontend App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
EOF
Build a docker image using the Dockerfile (Same as base image with just additional label)
1
docker build -t sakharamshinde/cmatrix .
Verify if the new images is created with the defined tag.
1
docker images
Create a container using the new image and ssh into the container
1
docker run --rm -it sakharamshinde/cmatrix sh
Once we are into the shell of the container, execute below steps to get the cmatrix running inside the container.
- Verify the Hostname
1
hostname
- Clone the Repository,
this will fail
1 2
# git clone https://github.com/abishekvashok/cmatrix.git
Since git is not installed in the base image, we will install the git tool.
1
apk update
1
apk add git
- Clone the repo
1
git clone https://github.com/abishekvashok/cmatrix.git
- Switch to the repo dir and check the contents
1
cd cmatrix
1
ls -l
Similarly, install the required packages required to build the cmatrix screensave
- Prepare compilation, will fail, missing autoconf
1
autoreconf -i
- Install autoconf
1
apk add autoconf
- Prepare compilation, will fail, missing automake
1
autoreconf -i
- Install automake
1
apk add automake
- Prepare compilation, will succeed, confirm with echo $?
1
autoreconf -i
- Verify it the install was successful
1
echo $?
- Prepare configure, will fail, missing compiler
1
./configure LDFLAGS="-static"
- Install compiler
1
apk add alpine-sdk
- Prepare configure, will fail, missing dependencies
1
./configure LDFLAGS="-static"
- Install dependencies and create missing directories
1
apk add ncurses-dev ncurses-static
1
mkdir -p /usr/lib/kbd/consolefonts /usr/share/consolefonts
- Prepare configure, will succeed
1
./configure LDFLAGS="-static"
- Compile and view result
1
make
- Check the created binary
1
ls -l ./cmatrix
- Run cmatrix
1
./cmatrix
Build a docker image for the cmatrix app using all the command used above.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
cat <<EOF> ./Dockerfile FROM alpine LABEL org.opencontainers.image.authors="Sakharam Shinde" RUN apk update RUN apk add git RUN git clone https://github.com/abishekvashok/cmatrix.git . RUN cd cmatrix RUN apk add autoconf RUN apk add automake RUN autoreconf -i RUN apk add alpine-sdk RUN apk add ncurses-dev ncurses-static RUN mkdir -p /usr/lib/kbd/consolefonts /usr/share/consolefonts RUN ./configure LDFLAGS="-static" RUN make CMD ["./cmatrix"] EOF
- Build a new image with the updated Dockerfile
1
docker build -t sakharamshinde/cmatrix .
- Run the new image, this will fail
1
docker run --rm -it sakharamshinde/cmatrix
- Specify the working directory for the Dockerfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
cat <<EOF> ./Dockerfile FROM alpine LABEL org.opencontainers.image.authors="Sakharam Shinde" WORKDIR /cmatrix RUN apk update RUN apk add git RUN git clone https://github.com/abishekvashok/cmatrix.git . RUN apk add autoconf RUN apk add automake RUN autoreconf -i RUN apk add alpine-sdk RUN apk add ncurses-dev ncurses-static RUN mkdir -p /usr/lib/kbd/consolefonts /usr/share/consolefonts RUN ./configure LDFLAGS="-static" RUN make CMD ["./cmatrix"] EOF
- Build a new image with the updated Dockerfile
1
docker build -t sakharamshinde/cmatrix .
- Run the new image, this will succeed
1
docker run --rm -it sakharamshinde/cmatrix
Check the size of the new image and inspect the layers
1
docker images
1
docker history sakharamshinde/cmatrix
To reduce the number of layers, we will combine common commands into one
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
cat <<EOF> ./Dockerfile FROM alpine LABEL org.opencontainers.image.authors="Sakharam Shinde" WORKDIR /cmatrix RUN apk update --no-cache && \ apk add git autoconf automake alpine-sdk ncurses-dev ncurses-static RUN git clone https://github.com/abishekvashok/cmatrix.git . RUN autoreconf -i RUN mkdir -p /usr/lib/kbd/consolefonts /usr/share/consolefonts RUN ./configure LDFLAGS="-static" RUN make CMD ["./cmatrix"] EOF
- Build the image
1
docker build -t sakharamshinde/cmatrix .
- Run the new image
1
docker run --rm -it sakharamshinde/cmatrix
Check the size of the image and inspect the layers
1
docker images
1
docker history sakharamshinde/cmatrix
To reduce the size further, we can combine all the RUN commands
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
cat <<EOF> ./Dockerfile FROM alpine LABEL org.opencontainers.image.authors="Sakharam Shinde" WORKDIR /cmatrix RUN apk update --no-cache && \ apk add git autoconf automake alpine-sdk ncurses-dev ncurses-static && \ git clone https://github.com/abishekvashok/cmatrix.git . && \ autoreconf -i && \ mkdir -p /usr/lib/kbd/consolefonts /usr/share/consolefonts && \ ./configure LDFLAGS="-static" && \ make CMD ["./cmatrix"] EOF
- Build the image
1
docker build -t sakharamshinde/cmatrix .
- Run the new image
1
docker run --rm -it sakharamshinde/cmatrix
Check the size of the image and inspect the layers
1
docker images
1
docker history sakharamshinde/cmatrix
Build the image using multi-stage docker build
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
cat <<EOF> ./Dockerfile # Build Container Image FROM alpine AS cmatrixbuilder WORKDIR /cmatrix RUN apk update --no-cache && \ apk add git autoconf automake alpine-sdk ncurses-dev ncurses-static && \ git clone https://github.com/abishekvashok/cmatrix.git . && \ autoreconf -i && \ mkdir -p /usr/lib/kbd/consolefonts /usr/share/consolefonts && \ ./configure LDFLAGS="-static" && \ make # cmatrix Container Image FROM alpine LABEL org.opencontainers.image.authors="Sakharam Shinde" \ RUN apk update --no-cache && \ apk add ncurses-terminfo-base COPY --from=cmatrixbuilder /cmatrix/cmatrix /cmatrix CMD ["./cmatrix"] EOF
- Build the image
1
docker build -t sakharamshinde/cmatrixms .
- Run the new image
1
docker run --rm -it sakharamshinde/cmatrixms
Check the user running the container
1
docker run --rm -it sakharamshinde/cmatrixms whoami
Run the container as a user instead of root
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
cat <<EOF> ./Dockerfile # Build Container Image FROM alpine AS cmatrixbuilder WORKDIR /cmatrix RUN apk update --no-cache && \ apk add git autoconf automake alpine-sdk ncurses-dev ncurses-static && \ git clone https://github.com/abishekvashok/cmatrix.git . && \ autoreconf -i && \ mkdir -p /usr/lib/kbd/consolefonts /usr/share/consolefonts && \ ./configure LDFLAGS="-static" && \ make # cmatrix Container Image FROM alpine LABEL org.opencontainers.image.authors="Sakharam Shinde" \ RUN apk update --no-cache && \ apk add ncurses-terminfo-base && \ adduser -g "Sakharam" -s /usr/sbin/nologin -D -H sakharam COPY --from=cmatrixbuilder /cmatrix/cmatrix /cmatrix USER sakharam CMD ["./cmatrix"] EOF
- Build the image
1
docker build -t sakharamshinde/cmatrixms .
- Run the new image
1
docker run --rm -it sakharamshinde/cmatrixms
Run the container with entrpoint and commands
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
cat <<EOF> ./Dockerfile # Build Container Image FROM alpine AS cmatrixbuilder WORKDIR /cmatrix RUN apk update --no-cache && \ apk add git autoconf automake alpine-sdk ncurses-dev ncurses-static && \ git clone https://github.com/abishekvashok/cmatrix.git . && \ autoreconf -i && \ mkdir -p /usr/lib/kbd/consolefonts /usr/share/consolefonts && \ ./configure LDFLAGS="-static" && \ make # cmatrix Container Image FROM alpine LABEL org.opencontainers.image.authors="Sakharam Shinde" \ RUN apk update --no-cache && \ apk add ncurses-terminfo-base && \ adduser -g "Sakharam" -s /usr/sbin/nologin -D -H sakharam COPY --from=cmatrixbuilder /cmatrix/cmatrix /cmatrix USER sakharam ENTRYPOINT ["./cmatrix"] CMD ["-b"] EOF
- Build the image
1
docker build -t sakharamshinde/cmatrixms .
- Run the new image
1
docker run --rm -it sakharamshinde/cmatrixms --help