FROM # create a new build stage from a base image. ARG # use build-time variables. LABEL # add metadata to an image. ENV # set environment variables. RUN # execute build commands. COPY # copy files and directories. CMD # specify default commands. ENTRYPOINT # specify default executable. USER # set user and group id. VOLUME # create volume mounts. WORKDIR # change working directory. EXPOSE # describe which ports your application is listening on. ADD # add local or remote files and directories. HEALTHCHECK # check a container's health on startup. MAINTAINER # specify the author of an image. ONBUILD # specify instructions for when the image is used in a build. SHELL # set the default shell of an image. STOPSIGNAL # specify the system call signal for exiting a container.See these pages for more information:
DOCKER_BUILDKIT=0
before using the docker build
command:$ DOCKER_BUILDKIT=0 docker build [OPTIONS] PATH | URL | -This disables Docker BuildKit, which is now the default builder and offers improved performance, output, and caching. It's recommended to enable BuildKit (
DOCKER_BUILDKIT=1
) or simply omit the variable.FROM [--platform=<platform>] <image> [AS <name>] FROM [--platform=<platform>] <image>[:<tag>] [AS <name>] FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]The FROM instruction creates a new build stage from a base image.
FROM ubuntu:latest
ARG <name>[=<default value>] [<name>[=<default value>]...]The ARG instruction uses build-time variables (along with their default values).
ARG image_version="latest"
LABEL <key>=<value> [<key>=<value>...]The LABEL instruction adds metadata to an image.
LABEL IMAGE_NAME="Ubuntu $image_version"Note that the label is using a variable name which, in this case, references the argument defined by the instruction ARG.
$ vi Dockerfile
FROM ubuntu:latest ARG image_version="latest" LABEL IMAGE_NAME="Ubuntu $image_version"Let's build the Dockerfile:
$ docker build -t ubuntu-base:latest --build-arg image_version="1.0" .You can inspect the created image to check the labels:
$ docker image inspect ubuntu-base:latest --format '{{json .Config.Labels}}' | jq
{ "IMAGE_NAME": "Ubuntu 1.0" }
ENV <key>=<value> [<key>=<value>...]The ENV instruction sets environment variables (also available as regular variables during build-time).
ENV image_env="dev"Let's use a Dockerfile with the above instructions:
$ vi Dockerfile
FROM ubuntu:latest ARG image_version="latest" ENV image_env="dev" LABEL IMAGE_NAME="Ubuntu $image_version $image_env"Let's build the Dockerfile:
$ docker build -t ubuntu-base:latest .You can inspect the created image to check the labels.
$ docker image inspect ubuntu-base:latest --format '{{json .Config.Labels}}' | jq
{ "IMAGE_NAME": "Ubuntu latest dev" }Let's check the env variable within the container:
$ docker container run --rm -it ubuntu-base:latest /bin/bash -c 'env | grep image_env'
image_env=dev
# Shell form: RUN [OPTIONS] <command> ... # Exec form: RUN [OPTIONS] [ "<command>", ... ]The RUN instruction executes build commands.
RUN apt-get -y updateYou should combine multiple build execution commands into a single instruction whenever possible.
RUN apt-get -y install curl && apt-get -y install nginxYou should also avoid updating the operating system or upgrading libraries. If necessary, you should use a base image that you can build only when needed. The base image should also be used, where possible, to install third-party libraries.
COPY [OPTIONS] <src> ... <dest> COPY [OPTIONS] ["<src>", ... "<dest>"]The COPY instruction copies files and directories from the local filesystem into a Docker image.
COPY ./file1 /tmpYou can copy files or folders.
$ mkdir folder1 $ mkdir folder1/folder2 $ touch folder1/file1 $ touch folder1/folder2/file2Let's use a Dockerfile to copy files/folders into the Docker image:
$ vi Dockerfile
FROM ubuntu:latest RUN mkdir /opt/foo RUN mkdir /opt/bar COPY ./folder1/file1 /opt/foo COPY ./folder1 /opt/barLet's build the Dockerfile:
$ docker build -t ubuntu-copy:latest .You can check the copied files/folders
$ docker container run --rm -it ubuntu-copy:latest /bin/bash -c 'find /opt'
/opt /opt/bar /opt/bar/folder2 /opt/bar/folder2/file2 /opt/bar/file1 /opt/foo /opt/foo/file1
# Exec form: CMD ["executable", "parameter1", "parameter2", ...] CMD ["parameter1", "parameter2", ...] # when used with ENTRYPOINT # Shell form: CMD command parameter1 parameter2The CMD instruction specifies default commands.
$ vi Dockerfile
FROM ubuntu:latest CMD ["bash", "-x"]Let's build the Dockerfile:
$ docker build -t ubuntu-copy:latest .You can check the copied files/folders
$ docker container run --rm -it ubuntu-cmd:latest
+ '[' -z '\s-\v\$ ' ']' + shopt -s checkwinsize ... root@fd2b5bd60f7f:/
# Exec form: ENTRYPOINT ["executable", "parameter1", "parameter2", ...] # Shell form: ENTRYPOINT command parameter1 parameter2The ENTRYPOINT instruction specifies default executable.
$ vi Dockerfile
FROM ubuntu:latest ENTRYPOINT ["bash", "-c"] CMD ["top", "-o %CPU", "-H"]Let's build the Dockerfile:
$ docker build -t ubuntu-entrypoint-cmd:latest .You can check the copied files/folders
$ docker container run --rm -it ubuntu-entrypoint-cmd:latest
top - 09:52:48 up 20:39, 0 user, load average: 0.60, 0.58, 0.54 Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie %Cpu(s): 2.3 us, 2.2 sy, 0.0 ni, 94.6 id, 0.3 wa, 0.0 hi, 0.6 si, 0.0 st MiB Mem : 15884.0 total, 9379.6 free, 2099.5 used, 4728.7 buff/cache MiB Swap: 4096.0 total, 4096.0 free, 0.0 used. 13784.5 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 8856 5188 3060 R 0.0 0.0 0:00.01 top
USER <user>[:<group>] USER <UID>[:<GID>]The USER instruction sets the user that will be used to run the processes inside the container.
$ id mti
uid=1002(mti) gid=1002(tek) groups=1002(tek)Let's first try a Dockerfile without the USER instruction:
$ vi Dockerfile-withoutuser
FROM ubuntu:latestLet's build the Dockerfile:
$ docker build -t ubuntu-withoutuser:latest -f Dockerfile-withoutuser .Let's check the user within the container:
$ docker container run --rm -it ubuntu-withoutuser:latest /bin/bash -c 'id'
uid=0(root) gid=0(root) groups=0(root)Let's try now a Dockerfile with the USER instruction:
$ vi Dockerfile-withuser
FROM ubuntu:latest RUN groupadd -r tek --gid=1002 && useradd -r -g tek --uid=1002 mti USER mtiLet's build the Dockerfile:
$ docker build -t ubuntu-withuser:latest -f Dockerfile-withuser .Let's check the user within the container:
$ docker container run --rm -it ubuntu-withuser:latest /bin/bash -c 'id'
uid=1002(mti) gid=1002(tek) groups=1002(tek)Note that the Dockerfile create the group "tek" with the group id (gid) "1002". It also create the user "mti" with the user id (uid) "1002" and the group id (gid) "1002". The image that we create from this Dockerfile will run with the user "mti".
VOLUME ["/data"]The VOLUME instruction creates volume mounts.
$ vi Dockerfile-nginx-mounted-log-dir
FROM nginx:latest #removing the redirection to stdout/stderr to allow writing logs to directory RUN rm -f /var/log/nginx/access.log && rm -f /var/log/nginx/error.log VOLUME /var/log/nginxLet's build the Dockerfile:
$ docker build -t nginx-mounted-log-dir:latest -f Dockerfile-nginx-mounted-log-dir .Let's create a local directroy:
$ mkdir ./nginx-loc-dirLet's run the nginx image (the host's directory ./nginx-loc-dir is mounted to the container's directory /var/log/nginx):
$ docker container run -d -P -v ./nginx-loc-dir:/var/log/nginx nginx-mounted-log-dir:latest
0a6ea9efbc1f264287aa2b146d77423fd5d8e9070b7aebd0a4d36d148631c16cCheck the nginx process:
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8491a320ecd8 nginx-mounted-log-dir:latest "/docker-entrypoint.…" 8 seconds ago Up 6 seconds 0.0.0.0:32770->80/tcp zen_shternLet's access nginx at the published port 32770:
$ curl http://localhost:32770Check the nginx logs:
$ ls -al ./nginx-loc-dir/
-rw-r--r-- 1 root root 91 access.log -rw-r--r-- 1 root root 0 error.log
$ cat ./nginx-loc-dir/access.log
172.17.0.1 - - [03/Aug/2020:03:22:16 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.58.0" "-"
WORKDIR /path/to/workdirThe WORKDIR instruction sets the working directory for the remaining build instructions.
$ vi Dockerfile-withworkdir
FROM ubuntu:latest WORKDIR /tmpLet's build the Dockerfile:
$ docker build -t ubuntu-withworkdir:latest -f Dockerfile-withworkdir .Let's check the working directory within the container:
$ docker container run --rm -it ubuntu-withworkdir:latest /bin/bash -c 'pwd'
/tmp
EXPOSE <port> [<port>/<protocol>...]The EXPOSE instruction informs Docker that the container should listen on the specified ports. You still need to manually publish the ports when running the container. Use the -p flag to publish and map ports. Use the -P flag to publish all exposed ports and map them to ephemeral higher-order host ports on the host. By default, ports listen on TCP but you can explicitly set UDP.
$ vi Dockerfile-expose
FROM nginx:latest EXPOSE 80/tcp EXPOSE 80/udpLet's build the Dockerfile:
$ docker build -t nginx-expose:latest -f Dockerfile-expose .Let's check the exposed port:
$ docker container run -d -p 8080:80 nginx-expose:latest
$ curl -s -o /dev/null -w "%{http_code}" http://localhost:8080
200