Overview
Dockerfile
Instructions are summarized.
- Docker version: v19.03
Simplified chart
FROM
Acquire by specifying the base image. The first line is this command. Specify an image from Docker Hub or a private Docker repository.
- No tag specified:
latest
pull
Dockerfile
FROM centos:7.7.1908
ENTRYPOINT [ "/bin/bash" ]
$ docker image build --file Dockerfile -t testrepo:test .
$ docker image ls --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
REPOSITORY TAG SIZE
testrepo test 204MB # < -The image created this time
centos 7.7.1908 204MB # < -Base image
- Tag specified: Pull with specified tag, basically should be specified
Dockerfile
FROM centos
ENTRYPOINT ["/bin/bash"]
$ docker image build --file Dockerfile -t testrepo:test .
$ docker image ls --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
REPOSITORY TAG SIZE
Testrepo Test 220MB # <- created this time the image
Centos Latest 220MB # <- based image
RUN
Execute the specified command. It is described later in Tips, but should be described together as much as possible.
Dockerfile
FROM centos:8
RUN yum install -y httpd iproute && \
echo "Test" > /var/www/html/index.html
ENTRYPOINT ["/usr/sbin/httpd"]
ENTRYPOINT / CMD
Specifies the command to be executed when the container is started. An image that is written once at the end of the Dockerfile.
Dockerfile
FROM centos:8ENTRYPOINT ["df"]
CMD ["-H", "."]
Specify the command to be specified by separating each space with a comma. For example go run main.go
, if you want to specify:
Dockerfile
ENTRYPOINT ["go", "run", "main.go"]
Difference between ENTRYPOINT and CMD
ENTRYPOINT
Is always executed as is,CMD
can be overwritten by specifying an argument when starting the container. Taking advantage of this property, you can write the ENTRYPOINT
command part CMD
and the command option part. Assuming that the image is built with the above Dockerfile, the difference between the concrete execution results when starting the container with arguments and when starting the container without arguments is shown below.
- No argument:
df -H .
is executed.
$ docker run override_test
Filesystem Size Used Avail Use% Mounted on
overlay 63G 2.1G 58G 4% /
- With argument (
--help
):df --help
is executed. You can see that the CMD part is overwritten by the options specified on the command line.
$ docker run docker_test --help
Usage: df [OPTION]... [FILE]...
Show information about the file system on which each FILE resides,
or all file systems by default.Mandatory arguments to long options are mandatory for short options too.
-a, --all include pseudo, duplicate, inaccessible file systems
COPY
Copy a file or directory from the host machine into the container. Directory structure of host machine
.
├── Dockerfile
├── copied
│ ├── subfile.txt
│ └── subfile2.txt
└── copyfile.txt
Dockerfile
FROM centos:latestRUN mkdir -p / app
# file unit
COPY ./copyfile.txt / app
# directory * It is necessary to specify the directory name of the copy destination.
COPY ./copydir / app / subdir
$ docker image build --file Dockerfile -t centos:copytest .
$ docker container run centos:copytest ls -ltR /app
/app:
total 8
drwxr-xr-x 2 root root 4096 Jan 12 13:27 subdir
-rw-r--r-- 1 root root 6 Jan 12 13:18 copyfile.txt/app/subdir:
total 4
-rw-r--r-- 1 root root 0 Jan 12 13:25 subfile2.txt
-rw-r--r-- 1 root root 8 Jan 12 13:19 subfile.txt
ADD
COPY
Similarly, copy the file from the host machine into the container. (Above Dockerfile of COPY
the ADD
will be the same result as) However, ADD
when you use the, if the copy file is a compressed file, will be performed automatically decompress.
Dockerfile
FROM centos:8RUN mkdir -p /app
# addtest.tar is a compressed file of
copydir ADD ./addtest.tar/app
Terminal
$ docker image build --file add/Dockerfile -t centos:addtest .
$ docker container run centos:addtest ls -lR /app
/app:
total 4
drwxr-xr-x 2 501 games 4096 Jan 12 13:25 copydir/app/copydir:
total 4
-rw-r--r-- 1 501 games 8 Jan 12 13:19 subfile.txt
-rw-r--r-- 1 501 games 0 Jan 12 13:25 subfile2.txt
# There is no tar file itself and decompression Existed
ef COPY
the case of
Terminal
$ docker container run testrepo:copy ls -lR /app
/app:
total 4
-rw-r--r-- 1 root root 177 Jan 12 13:31 addtest.tar # leave the compressed file
Separation from COPY
- When copying is simply performed => COPY
- To copy and decompress => ADD
ENV
Add environment variables to the execution container.
Dockerfile
FROM centos:8
ENV NEW_ENV='env-value'
ENTRYPOINT ["/bin/bash"]
Terminal
$ docker image build --file Dockerfile -t centos:envtest .
$ docker container run -it centos:envtest
[root@de6dc0f2577e /]# env
LANG=en_US.UTF-8
HOSTNAME=de6dc0f2577e
NEW_ENV=env-value # fileで追加した環境変数
EXPOSE
Put the specified port in the LISTEN state.
Dockerfile
FROM python:3.8-slim-busterCOPY . /
RUN pip install -r /app/requirements.txtEXPOSE 9876
ENTRYPOINT [ "gunicorn", "flask_app:app" ]
CMD [ "-c", "/app/config/gunicorn_settings.py" ]
Terminal
$ docker image build --file Dockerfile -t python:flask .
$ docker container run --name exposetest python:flask
$ docker container ps --format "table {{.Image}}\t{{.Ports}}"
IMAGE PORTS NAMES
flask 9876/tcp exposetest
a2556b3a812 worktest
# LISTENED port number is displayed in PORTS
WORKDIR
Change working directory. In Dockerfilecd
Dockerfile
FROM centos:8
RUN mkdir -p /test
RUN echo "before workdir" > before.txtWORKDIR /test
RUN echo "after workdir" > after.txtENTRYPOINT ["/bin/bash"]
Terminal
$ docker image build --file Dockerfile -t centos: workdir .
$ docker container run -it --name workdirtest centos: workdir
[ root @ 4cd5accab742 test ] # pwd
/ test # The last WORKDIR path is the base path for starting the container to become
[ root Atto 4Cd5accab742 Test ] # Ls .. | Grep before
Before.Txt # before the presence in the root directory that you have created before WORKDIR
[ root Atto 4Cd5accab742 Test ] . # Ls
After.Txt # for after is created after WORKDIR Exists in the / test directory
Tips
Light weight with multi-stage build
A multi-stage build is like a technique to reduce the weight of the final finished image. As an example, Go
let's compare the image size between when the application is applied with multi-stage build and when it is not.
- No multi-stage build
Dockerfile
FROM golang:1.13-alpine
COPY ./main.go ./
RUN go build -o /app ./main.go
ENTRYPOINT ["/app"]
- Multi-stage build available
Dockerfile
# 1st step (build)
FROM golang: 1.13-alpine as builder
COPY ./main.go ./
RUN go build -o / app ./main.go# Second stage (this is the completed image)
# Select a lightweight image that meets the minimum requirements for the base
FROM alpine: 3.11
# Copy the required items from the first stage container
COPY --from = builder / app.
ENTRYPOINT [" ./app "]
- Check size
Terminal
REPOSITORY TAG SIZE
golang nonmultistage 361MB
golang multistage 7.6MB # overwhelmingly light
Combine instructions as much as possible
An image cache is built for each Dockerfile instruction. Minimizing this number of image cache layers is considered a best practice, which can result in lighter weight and faster builds. Specifically, perform the following actions.
- RUN instructions are connected by “backslash + &&”
- Keep COPY / ADD instructions as small as possible
In particular, RUN
there is a problem with the cache at the time of build, yum update
and if you do not connect them with yum install
the &&
word , you may get stuck. (The cache is not described in this article.)
URL can be specified in ADD instruction, but it is not written
Use curl
or when retrieving resources from a URL in order to reduce the number of layers and reduce the image weight wget
.
Example ( excerpt from Best practices )
Dockerfile
# Good
RUN mkdir -p /usr/src/things \
&& curl -SL http://example.com/big.tar.xz \
| tar -xJC /usr/src/things \
&& make -C /usr/src/things all# Bad
ADD http://example.com/big.tar.xz /usr/src/things/
RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
RUN make -C /usr/src/things all