Docker Image Building

Dockerfile

Posted by Rico's Nerd Cluster on June 3, 2024

Construct Of An Docker Image And Its Building Process

A Docker image is like a box of Oreo. Its final image is like multiple Oreos (layer) stacked on top of each other. A layer could be built from multiple building stages (like our favorite chocolate topping), and each stage consists of smaller layers.

Now Let’s walk through a basic example

Source: Sunny Beatteay

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Stage 0: Build Stage
FROM node:18-alpine AS build

WORKDIR /app
COPY package*.json ./
RUN npm install --production
COPY . .
RUN npm run build

# Stage 1: Final Stage
FROM node:18-alpine

WORKDIR /app
COPY --from=build /app/dist ./dist
CMD ["node", "dist/main.js"]

Layers: Docker images are built in layers.

1
2
3
WORKDIR /app
COPY package*.json ./
RUN npm install --production
  • Each layer is an instruction such as RUN, COPY, ADD, etc. Each layer is stacked on top of each other. The above is a three-layer model.

Stages: The above is a two layer build. Each stage starts from a FROM command, which launches a base image.

  • Stage 0 creates artifacts / build of the custom app (e.g., RUN npx run build). It consists of several layers
  • Stage 1 is created by launching a new base image node:18-alpine and copying the build artifacts from Stage 0. The final image only contains layers from the last stage and files copied from previous stages. So Stage 0 is effectively discarded.

  • To use a custom Dockerfile, use the -f arg: docker build -f Dockerfile_test_container . -t ros-noetic-simple-robotics-tests

Create An Entrypoint

An entrypoint is a script that runs once a container starts. Here, we need to copy the entry point to a common location, then execute it

1
2
3
4
5
COPY entrypoint_rgbd_slam_docker.sh /entrypoint_rgbd_slam_docker.sh
# RUN chmod +x /entrypoint_rgbd_slam_docker.sh
ENTRYPOINT ["/entrypoint_rgbd_slam_docker.sh"]
# must follow ENTRYPOINT, otherwise the container won't execute bash
CMD ["bash"]    

In entrypoint, make sure the last line has

1
2
3
4
...

# Execute the CMD command (bash) by replacing the shell with the CMD command in Dockerfile
exec "$@"
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
# Add Deadsnakes PPA and install Python 3.10
RUN apt-get update && apt-get install -y software-properties-common && \
    add-apt-repository ppa:deadsnakes/ppa && \
    apt-get update && \
    apt-get install -y python3.10 python3.10-dev python3.10-venv python3.10-distutils && \
    rm -rf /var/lib/apt/lists/*

# Install pip for Python 3.10
RUN wget https://bootstrap.pypa.io/get-pip.py && \
    python3.10 get-pip.py && \
    rm get-pip.py

# Update alternatives to set python3 to python3.10
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 1 && \
    update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 2 && \
    update-alternatives --set python3 /usr/bin/python3.10

# Set environment variables for Python
ENV PYTHON_VERSION=3.10
ENV PYTHON_BIN=/usr/bin/python${PYTHON_VERSION}
ENV PIP_BIN=/usr/local/bin/pip

# Upgrade pip and setuptools, then install a compatible PyYAML version
RUN pip3 install --upgrade pip setuptools wheel && \
    pip3 install --force-reinstall --ignore-installed PyYAML==6.0