Dockerfile
lastmod 2025-04-11created 2015-12-0931 edits
Notes on Dockerfile.
Examples
- Selenium WebDriver#Selenium for Dockerfile - How to install Chrome and ChromeDriver
Build
Build a Dockerfile as follows.
Command
-
FROM: Specifies the parent image, that is, which image the new image is created from. -
MAINTAINER: Information about the person who creates and maintains the Dockerfile. -
ENV: Sets environment variables. -
EXPOSE: Specifies the ports to open on the virtual machine. Same as the--exposeoption of thedocker runcommand. -
WORKDIR: Sets the working directory in which commands are run. -
ADD: Adds files to the image. The format isADD [복사할 파일 경로] [이미지에서 파일이 위치할 경로](source file path, destination path in the image).- It is good practice to verify files added with the ADD instruction with a hash-based checksum.
CMD: Specifies the command to run in the container. However, it is not run if COMMAND is given in docker run [OPTIONS] IMAGE [COMMAND] [ARG...].- Only needed in special cases, such as building a base image containing an operating system.
- It doesn't guarantee stability, so use COPY instead.
ENTRYPOINT: Similar to CMD. However, if COMMAND is given in docker run [OPTIONS] IMAGE [COMMAND] [ARG...], it is appended as additional arguments to ENTRYPOINT. 1 RUN: Defines commands to run in the container when building the image COPY: Copies files and directories from the host to the container ARG: Variables used when running docker image build EXPOSE: Ports the container exposes VOLUME: Creates a point that the host or other containers can mount LABEL: Metadata added to the image STOPSIGNAL: Sets the system signal that stops the container when sent to it HEALTHCHECK: Runs a command inside the container and uses the result for health checks- Usage example - Docker Compose#Healthcheck
USER: The container user when the container runs- During the image build, RUN instructions after USER also run with that user's permissions.
ONBUILD: Defines commands run inside the container; they are not run in the image.- They run when another image is built using the image that defines ONBUILD as its base image.
Setup
You usually start as follows.
For CentOS 7:
FROM centos:7
MAINTAINER yourname <[email protected]>
For Ubuntu 14.04:
FROM ubuntu:14.04
MAINTAINER yourname <[email protected]>
Example
FROM ubuntu:12.04
MAINTAINER Daekwon Kim <[email protected]>
# COMMENT
RUN apt-get -qq -y install git curl build-essential
RUN apt-get -qq -y install apache2
ENV APACHE_RUN_USER www-data
# ...
RUN ./var/www/moniwiki/secure.sh
EXPOSE 80
CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]
ENV APP_HOME /myapp
WORKDIR $APP_HOME
ADD Gemfile* $APP_HOME/
ADD . $APP_HOME
Base images
- scratch: An empty image
- If HTTPS communication is needed, you must add cacert.pem to /etc/ssl/certs.
- Debugging is hard, too
- busybox: An image with basic utilities (echo, ls, etc.)
- No package manager.
- Debugging is somewhat better.
- alpine: Based on busybox and only 4MB, but has the apk package manager.
- Uses musl instead of glibc.
-
apk add --no-cache package -
apk add --no-cache --virtual=ailas package && apk del --no-cache ailas
-
- distroless images
- Images focused on a language, without operating system features.
- Available at distroless, and mostly distributed by Google.
- The gcr.io/distroless/base image is glibc-based and suited to running compiled applications. (Go)
- Contains only minimal libraries, such as ca-certificates and TLS/SSL-related libraries.
- Reportedly, CVE vulnerabilities are also patched.
MySQL dockerfile
- Creating a MySQL Docker Container
- Docker for the Really Impatient, Chapter 16 - 2. Writing a MySQL Database Dockerfile
FROM ubuntu:14.04
## apt-get 설치시 사용자 입력을 받지 않는다는 환경변수 설정.
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update
RUN echo "mysql-server mysql-server/root_password password" | debconf-set-selections
RUN echo "mysql-server mysql-server/root_password_again password" | debconf-set-selections
RUN apt-get install -y mysql-server
WORKDIR /etc/mysql
RUN sed -i "s/127.0.0.1/0.0.0.0/g" my.cnf
Multi-stage build
Use a previous stage as a new stage
You can pick up where a previous stage left off by referring to it when using the FROM directive. For example:
FROM alpine:latest as builder
RUN apk --no-cache add build-base
FROM builder as build1
COPY source1.cpp source.cpp
RUN g++ -o /binary source.cpp
FROM builder as build2
COPY source2.cpp source.cpp
RUN g++ -o /binary source.cpp
Docker image build script
A bash script that builds an image for a project:
#!/usr/bin/env bash
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)
WORKING_DIR=$SCRIPT_DIR
DOCKERFILE_PATH=$SCRIPT_DIR/project-python-3.8.9.dockerfile
IMAGE_NAME=yourname/project
IMAGE_TAG=python-3.8.9
TAG_NAME=$IMAGE_NAME:$IMAGE_TAG
TAG_LATEST=$IMAGE_NAME:latest
USAGE_MESSAGE="
Build project docker image.
Usage: project-build.sh [options]
Available options are:
-p, --push Push an image to a registry.
-l, --latest Add 'latest' tag.
-n, --dry-run Don’t actually do anything, just show what would be done.
-h, --help Print this message.
"
function exit_on_error
{
local code=$?
if [[ $code -ne 0 ]]; then
exit $code
fi
}
function run_command
{
local dry_run=$1
shift
if [[ $dry_run -eq 1 ]]; then
echo "$@"
else
"$@"
fi
exit_on_error
}
function recc_node_build_main
{
local src="$OPM_HOME/INFORMATION"
local enable_push=0
local add_latest=0
local dry_run=0
while [[ ! -z $1 ]]; do
case $1 in
-h|--help)
echo "$USAGE_MESSAGE"
return 0
;;
-p|--push)
enable_push=1
shift
;;
-n|--dry-run)
dry_run=1
shift
;;
-l|--latest)
add_latest=1
shift
;;
*)
break
;;
esac
done
local build_commands=("--file" "$DOCKERFILE_PATH" "-t" "$TAG_NAME")
if [[ $add_latest -eq 1 ]]; then
build_commands+=("-t" "$TAG_LATEST")
fi
build_commands+=("$WORKING_DIR")
run_command $dry_run docker build ${build_commands[*]}
if [[ $enable_push -eq 0 ]]; then
return 0
fi
run_command $dry_run docker push $TAG_NAME
if [[ $add_latest -eq 0 ]]; then
return 0
fi
run_command $dry_run docker push $TAG_LATEST
}
recc_node_build_main "$@"
dockerd tuning
-
max-concurrent-downloads: Default is 3. Increases the number of image threads downloaded at once by docker image pull. -
max-concurrent-uploads: Default is 5. Increases the number of image upload threads during docker image push. -
registry-mirrors: Creating a mirror registry of Docker hub can help improve traffic.
Tools
- hadolint - Verifies that the image was built according to Dockerfile best practices.
- container-structure-test - yaml-based tests.
- goss - yaml-based tests. It can check whether ports and services are actually serving, so it seems more useful.
- Vault - secret
- dockerfmt - Dockerfile formatter
See also
Favorite site
- Docker for the Really Impatient, Chapter 16 - 1. Writing a WordPress Dockerfile
- Docker for the Really Impatient, Chapter 16 - 2. Writing a MySQL Database Dockerfile
- Docker for the Really Impatient, Chapter 16 - 3. Creating WordPress and Database Containers
- Docker, Rails, & Docker Compose together in your development workflow
- Everything About Dockerfile | Gracefullight
Examples
Guide
- [Recommended] Docker Best Practices for Python Developers | TestDriven.io 2 - Docker best practices for Python developers
References
-
Docker for the Really Impatient, Chapter 7 - 6. ENTRYPOINT ↩
-
Docker_Best_Practices_for_Python_Developers_TestDriven.io.pdf ↩
Pages that link here