Docker's Common Use
In this post, I will cover Docker’s common use based on my experience.
I. Docker
1. Writing Dockerfile
The basic structure of Dockerfile
FROM <base_image_name>:<version> |
Common used instructions
Instructions for build
- FROM
- ARG
- WORKDIR
- COPY/ADD
- RUN
FROM
Create a new build stage from a base image. For example,
FROM alpine:latest |
FROM node:22-alpine |
ARG
Create build-time variables. For example,
# define variable |
WORKDIR
Change the working directory. Like the cd
command on Linux. For example,
WORKDIR /app |
COPY
Copy files and directories from a source location on the host machine into the filesystem of the Docker image at a specified destination. You can add .dockerignore
to ignore files. For example,
COPY . . |
ADD
Copy local files and download the file from that URL. When you copy local files, it’s best to use COPY
.
RUN
Run commands. It’s better to run multiple commands at once via && concatenation. For example,
RUN npm install |
Instructions for container
- ENV
- EXPOSE
- USER
- ENTRYPOINT/CMD
ENV
Set environment variables for the container. For example,
ENV TZ=Asia/Shanghai |
EXPOSE
Describe which ports your application is listening on. It is used in a Dockerfile to indicate which port(s) the container will listen on at runtime. While it does not actually publish the ports, it serves as documentation for anyone who uses the image and helps improve the clarity of how to run the container. For example,
EXPOSE 80 |
USER
Set user and group ID. For example,
# create user and group |
ENTRYPOINT
Specify the default executable. Specifies the command that should always run; not overridden by runtime arguments. For example,
ENTRYPOINT ["java","-jar","/app.jar"] |
- Only can run
java
command.
CMD
Specify default commands. Specifies default arguments for ENTRYPOINT
or acts as the command to run when no command is provided; can be overridden by runtime arguments. For example,
CMD ["java","-jar","/app.jar"] |
- By default, it runs
java
command. It can also run another command by overriding runtime arguments, for example,docker run my_container echo 'Hello World'
.
More Dockerfile instructions to see: Dockerfile reference
Common used base images
Avoid Using the latest
Tag. Specify exact versions of images for predictability and security. Using latest
can lead to unexpected changes.
Linux
alpine:3
(3MB). A security-oriented, lightweight, and minimal Docker image based on Alpine Linux. It’s a popular choice for many applications due to its small size and package management system (apk).
FROM alpine:3 |
ubuntu:25.04
(30MB)
FROM ubuntu:25.04 |
debian:12-slim
(27MB)
FROM debian:12-slim |
Java
- 21
amazoncorretto:21-alpine
(155MB)eclipse-temurin:21-alpine
(173MB),eclipse-temurin:21-jre-alpine
(69MB)
- 8
openjdk:8-jdk-slim
,openjdk:8-jre-slim
,openjdk:8-jdk-alpine
,openjdk:8-jre-alpine
Note openjdk docker images are deprecated.
Node.js
node:22-alpine
(52MB)
Nginx
nginx:stable-alpine
(16MB)
Python
python:3-alpine
(15MB)
Middleware
mysql/mysql-server:8.0
(160MB)redis:7-alpine
(15MB)postgres:17-alpine
(111MB)
Other
scratch
. 0 bytes (it’s an empty image). Thescratch
image is the ultimate minimal image. It is used to build completely statically compiled binaries (like Go applications). It is important to note that you can’t install any packages onscratch
since it’s literally an empty image.busybox:stable
(1MB). BusyBox combines tiny versions of many common UNIX utilities into a single small executable. It’s often used for simple tasks and scripts. Tools that busybox provided: sh, file operations (ls, cp, mv, rm, mkdir, touch, etc), text processing (cat, echo, grep, etc), networking utilities (ifconfig, ping, wget, telnet, etc), system utilities (ps, kill, top, free), and so on.
Search Docker images
To get the size of a Docker image before a pull
# for an official image the namespace is called library |
Differences between ENTRYPOINT
and CMD
?
ENTRYPOINT
: Specifies the command that should always run; not overridden by runtime arguments.CMD
: Specifies default arguments forENTRYPOINT
or acts as the command to run when no command is provided; can be overridden by runtime arguments.
For example:
Dockerfile
FROM ubuntu:20.04 |
docker build -t my-python-image . |
If you run the container without any command:
docker run my-python-image |
It runs: python3 app.py
.
If you want to run a different script instead:
docker run my-python-image another_script.py |
It runs: python3 another_script.py
.
Set timezone
ENV TZ=Asia/Shanghai |
To run the application as a non-root user
# Change permissions of some directories and files in the mapping volume before changing to a non-root user. |
Multi-stage Dockerfile
You can define multiple build stages, and copy files from the previous stage. For example,
# Build Stage |
2. Building Docker Image
docker build -t <image_name> . |
Commonly used options of docker build
-t, --tag
: Specify image name.--no-cache
: Do not use cache when building the image. Automatically update to use the latest base image according to the version of the base image.-f, --file
: Dockerfile file path relative to docker context root path. By default, it’s<container_content_root_path>/Dockerfile
. For example,./Dockerfile
.--platform
: Set target platform for build. For example,linux/amd64
(Linux),linux/arm64
(macOS).
For more options reference: Docker build documentation.
Note: Docker can’t translate the hostname of Docker containers during the build stage.
3. Running Docker Container
docker run -d --name <my_container> [,more_options] <image_name> |
Common used options of docker run
- Basic
-d, --detach
: Run the container in the background.--name
: Set container name.
- Environment
-e, --env
: Set environment variables. For example,-e "SPRING_PROFILES_ACTIVE=prod"
. You can also specify multiple-e
options to set multiple environment variables.--env-file
: Read in a file of environment variables. For example,--env-file .env
- Disk
--mount
: Attach a filesystem mount to the container. For detailed usage, see the content below.-v, --volume
: Bind mount a volume. For detailed usage, see the content below.
- Network
--network
: Connect a container to a network. Syntax:--network <network_name>
. For example:--network my_app
. You can also specify multiple--network
options to connect multiple networks. Docker compose network:<project_directory_name>_default
.-p, --publish
: Publish a container’s port(s) to the host. Syntax:-p host_port:container_port
. For example,-p 8080:8080
. You can also specify multiple-p
options to publish multiple ports.
- Interactive
-i, --interactive
: Keep STDIN open even if not attached.-t, --tty
: Allocate a pseudo-TTY.
- Others
--restart
: Restart policy to apply when a container exits.--rm
: It is used to automatically remove a container after it has stopped running. This is particularly useful for running temporary containers that are only needed for a short period of time and helps keep your system clean by avoiding the accumulation of stopped containers.-m, --memory
: Memory limit. For example,-m 2GB
.
For more options of docker run
reference: docker container run
docker run -v
1. Using a named volume
Named volumes are managed by Docker, and volumes created this way can be shared among multiple containers.
docker run -v my-volume:/app/data myimage |
2. Using a bind mount
A bind mount allows you to mount a specific directory or file from the host file system into the container.
docker run -v /path/on/host:/app/data myimage |
/path/on/host
is a file or directory on the host system./app/data
is the directory inside the container where the host directory will be mounted.
3. Read-Only Mount
You can make a volume or bind mount read-only by appending :ro
to the volume or bind mount specification.
docker run -v my-volume:/app/data:ro myimage |
4. Multiple Mounts
You can also specify multiple -v
options to mount multiple volumes or bind mounts into the same container.
docker run -v my-volume:/app/data -v /path/on/host:/app/config myimage |
docker run –mount
Syntax
docker run --mount type=<type>,source=<source>,target=<target>[,readonly] <image> |
type=<type>
: The type of mount. Possible values are:volume
: For a Docker-managed volume.bind
: For a bind mount to a specific host path.tmpfs
: For a temporary filesystem mount in memory.
source=<source>
: The source for the mount. This can be the name of a Docker volume (fortype=volume
) or a path on the host (fortype=bind
).target=<target>
: The path inside the container where the mount will be accessible.readonly
: Optional flag. If specified, the mount will be read-only for the container (i.e., no write operations will be allowed).<image>
: The name of the Docker image from which to create the container.
1. Using a Named Volume
docker run --mount type=volume,source=my-volume,target=/app/data myimage |
2. Using a Bind Mount
docker run --mount type=bind,source=/path/on/host,target=/app/data myimage |
3. Using a Tmpfs Mount
A tmpfs mount allows you to create a mount that resides in memory. This is useful for data that needs to be temporary.
docker run --mount type=tmpfs,target=/app/temp myimage |
/app/temp
is the directory inside the container where the temporary filesystem will be created.
4. Using Read-Only Mount
You can make any of the mounts read-only by adding the ,readonly
option.
docker run --mount type=volume,source=my-volume,target=/app/data,readonly myimage |
5. Multiple Mounts
You can specify multiple --mount
options when starting a container to use multiple mounts.
docker run --mount type=volume,source=my-volume,target=/app/data \ |
Run amd64 Docker image on arm64 (macOS)
Warning message
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested |
Solutions
docker run --platform linux/amd64 ... |
Run Docker container in interactive mode
docker run -it ... |
-i, --interactive
: Keep STDIN open even if not attached-t, --tty
: Allocate a pseudo-TTY
For example:
# connect to local postgres server container |
4. Stop and remove a Docker container
docker stop <container_name> || true && docker rm <container_name> || true |
5. View logs of the Docker container
docker logs -f <container_name> |
🚀II. Docker Compose
1. Writing Docker compose.yaml
The basic structure of compose.yaml
services: |