docker build
# since 18.09, backward compatible with docker build. default builder
docker buildx build
Docker builds images by reading the instructions from a Dockerfile. This is a text file containing instructions that adhere to a specific format needed to assemble your application into a container image.
Docker images consist of read-only layers, each resulting from an instruction in the Dockerfile. Layers are stacked sequentially and each one is a delta representing the changes applied to the previous layer.
Dockerfile 是一个描述如何创建 Docker 镜像所需步骤的文本文件。由一系列指令组成。
# 使用当前目录的Dockerfile创建镜像
docker build -t myimage1:latest .
# 使用指定目录的Dockerfile创建镜像
docker build -t myimage2:latest -f path/to/Dockerfile .
the most common types of instructions:
Instruction | Description |
---|---|
From |
Defines a base for your image. |
RUN |
Executes any commands in a new layer on top of the current image and commits the result. RUN also has a shell form for running commands. |
WORKDIR |
Sets the working directory for any RUN , CMD , ENTRYPOINT , COPY , and ADD instructions that follow it in the Dockerfile. |
COPY |
Copies new files or directories from and adds them to the filesystem of the container at the path . |
CMD |
Lets you define the default program that is run once you start the container based on this image. Each Dockerfile only has one CMD , and only the last CMD instance is respected when multiple exist. |
FROM
# tag默认latest
FROM [--platform=<platform>] <image> [AS <name>]
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
FROM openjdk:11-jre
The
FROM
instruction initializes a new build stage and sets the Base Image for subsequent instructions. As such, a validDockerfile
must start with aFROM
instruction.
- Optionally a name can be given to a new build stage by adding
AS name
to theFROM
instruction. The name can be used in subsequentFROM
andCOPY --from=
instructions to refer to the image built in this stage.
一条指令会在当前镜像的最顶层执行,并提交执行结果生成新的镜像层,供下一步使用。可以用&&
将多条指令合并成一个,指令太长可以用 \
换行。
RUN has 2 forms:
RUN
(shell form, the command is run in a shell, which by default is /bin/sh -c
on Linux or cmd /S /C
on Windows)RUN ["executable", "param1", "param2"]
(exec form)RUN /bin/bash -c 'echo hello'
# equivalent to
RUN ["/bin/bash", "-c", "echo hello"]
RUN apt-get update \
&& apt-get install vim
Unlike the shell form, the exec form does not invoke a command shell. This means that normal shell processing does not happen.
# will not do variable substitution on $HOME
RUN [ "echo", "$HOME" ]
# correct
RUN [ "sh", "-c", "echo $HOME" ]
COPY [--chown=:] ...
# This latter form is required for paths containing whitespace
COPY [--chown=:] ["",... ""]
The
path must be inside the context of the build。只能将复制本地文件至镜像内。
--from
参数用于在多阶段构建中,从前置构建或其他镜像复制文件。
ADD [--chown=:] [--checksum=] ...
# The latter form is required for paths containing whitespace.
ADD [--chown=:] ["",... ""]
If
is a local tar archive in a recognized compression format (identity, gzip, bzip2 or xz) then it is unpacked as a directory. Resources from remote URLs are not decompressed.
容器启动时运行的命令,只能有一条,多条的话最后一条生效
The CMD
instruction has three forms:
CMD ["executable","param1","param2"]
(exec form, this is the preferred form)CMD ["param1","param2"]
(as default parameters to ENTRYPOINT). If CMD
is used to provide default arguments for the ENTRYPOINT
instruction, both the CMD
and ENTRYPOINT
instructions should be specified with the JSON array format.CMD command param1 param2
(shell form, execute in /bin/sh -c
)容器启动时运行的命令,只能有一条,多条的话最后一条生效。使用docker run
命令创建容器时,ENTRYPOINT
不能被覆盖,只能设置额外参数。
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2
ENTRYPOINT ["java", "-jar", "/application.jar"]
举例1
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
docker run -it --rm --name test top -H
# 最终执行
top -b -H
举例2
FROM ubuntu
ENTRYPOINT exec top -b
docker run -it --rm --name test top
# 最终执行
top -b
- Dockerfile should specify at least one of
CMD
orENTRYPOINT
commands.ENTRYPOINT
should be defined when using the container as an executable.CMD
should be used as a way of defining default arguments for anENTRYPOINT
command or for executing an ad-hoc command in a container.CMD
will be overridden when running the container with alternative arguments.
- 如果Docker镜像的用途是运行应用程序或服务,比如运行一个MySQL,应该优先使用Exec格式的ENTRYPOINT指令。CMD可为ENTRYPOINT提供额外的默认参数,同时可利用docker run命令行替换默认参数。
- 如果想为容器设置默认的启动命令,可使用CMD指令。用户可在docker run命令行中替换此默认命令。
No ENTRYPOINT | ENTRYPOINT exec_entry p1_entry | ENTRYPOINT [“exec_entry”, “p1_entry”] | |
---|---|---|---|
No CMD | error, not allowed | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry |
CMD [“exec_cmd”, “p1_cmd”] | exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry exec_cmd p1_cmd |
CMD exec_cmd p1_cmd | /bin/sh -c exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd |
ENV = ...
ENV MY_NAME="John Doe"
ENV MY_DOG=Rex\ The\ Dog
ENV MY_CAT=fluffy
You can view the values using
docker inspect
, and change them usingdocker run --env
.=
The
VOLUME
instruction creates a mount point with the specified name and marks it as holding externally mounted volumes from native host or other containers.
VOLUME ["/data"]
FROM alpine
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol
The
WORKDIR
instruction sets the working directory for anyRUN
,CMD
,ENTRYPOINT
,COPY
andADD
instructions that follow it in theDockerfile
.
WORKDIR /path/to/workdir
The
ARG
instruction defines a variable that users can pass at build-time to the builder with thedocker build
command using the--build-arg
flag.=
ARG [=]
example: https://docs.npmjs.com/docker-and-private-modules
FROM node
ARG NPM_TOKEN
COPY .npmrc .npmrc
COPY package.json package.json
RUN npm install
RUN rm -f .npmrc
# Add your source files
COPY . .
CMD npm start
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
docker build --build-arg NPM_TOKEN=${NPM_TOKEN} .
# protocol默认tcp
EXPOSE [/...]
EXPOSE 8080
EXPOSE 6379/tcp 53/udp
LABEL:adds metadata to an image.
USER:指定之后的 RUN、CMD 和 ENTRYPOINT 指令执行使用的用户
对于 .
,旧的构建工具会把整个当前目录暴露给daemon,而对于BuildKit,只会暴露指令(例如COPY)使用到的路径。可以用dockerignore
排除某些目录(例如node_modules)
git repository
docker build -t hello-flask:latest https://github.com/zlx01/docker-build-url-context.git
With multi-stage builds, you use multiple
FROM
statements in your Dockerfile. EachFROM
instruction can use a different base, and each of them begins a new stage of the build. You can selectively copy artifacts from one stage to another, leaving behind everything you don’t want in the final image.
举例:
FROM node as build
WORKDIR /app
COPY . .
RUN npm i --registry=https://registry.npmmirror.com
RUN npm run build
FROM nginx
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
docker build -t vue3-test:v3 .
可以看到本地已经打包好镜像了,镜像大小和nginx接近,如果把node也包括进来,镜像竟然要达到接近1000MB,
跑起来看看
docker run -d -p 8090:80 vue3-test:v3
FROM maven:3.8.6-openjdk-11
COPY . .
RUN mvn -B package --file pom.xml
FROM openjdk:11
COPY --from=0 ./target/springboot-demo-0.0.1-SNAPSHOT.jar /usr/app/hello.jar
WORKDIR /usr/app
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "hello.jar"]
docker run -d -p 8080:8080 springboot-test:v1