This example demonstrates how to package a simple C application into a Docker container.
The repository contains:
helloworld.c— a simple application displaying information about its execution environment.Dockerfile.single— a single-stage build.Dockerfile.multistage— a multi-stage build.
After completing this example, you should be able to:
- Build a Docker image.
- Run a container.
- Understand the purpose of
FROM,COPY,RUN,WORKDIR,USER,CMD, andENTRYPOINT. - Compare single-stage and multi-stage builds.
- Explain why multi-stage builds produce smaller runtime images.
The program prints information about its execution environment:
- Container hostname
- Process identifier (PID)
- User identifier (UID)
- An optional environment variable (
NAME)
Example output:
Hostname : 8c43b0a0d77b
PID : 1
UID : 999
Hello World!
Build the image:
docker build \
-f Dockerfile.single \
-t hello:single .Run the container:
docker run --rm hello:singleOverride the environment variable:
docker run --rm \
-e NAME=Alice \
hello:singleExample output:
Hostname : 8c43b0a0d77b
PID : 1
UID : 999
Hello Alice!
Build the image:
docker build \
-f Dockerfile.multistage \
-t hello:multi .Run the container:
docker run --rm hello:multiThe application behaves exactly the same, but the runtime image contains only the executable and the required runtime components.
List the images:
docker images helloor
docker image lsNotice that the multi-stage image is significantly smaller because it does not include the compiler and development tools.
You can also inspect the image layers:
docker history hello:singledocker history hello:multiTry the following commands.
docker run --rm \
-e NAME=Docker \
hello:multidocker run --rm \
--hostname=my-container \
hello:multiThe Dockerfile creates a non-root user.
Verify the displayed UID and compare it with an image running as the root user.