赞
踩
# escape=\ (backslash) # This dockerfile uses the ubuntu:xeniel image # VERSION 2 - EDITION 1 # Author: docker_user # Command format: Instruction [arguments / command] # Base image to use, this must be set as the first line FROM ubuntu:xeniel # Maintainer: docker user <docker user at email.com> @docker user ) LABEL maintainer docker user<docker user@email.com> # Commands to update the image RUN echo "deb http://archive.ubuntu.com/ubuntu/ xeniel main universe" >> /etc/apt/sources.list RUN apt-get update && apt-get install -y nginx RUN echo "\n daemon off;" >> /etc/nginx/nginx.conf # Commands when creating a new container CMD /usr/sbin/nginx
分类 | 指令 | 说明 |
---|---|---|
配置指令 | ARG | 定义创建镜像过程中使用的变量(镜像创建完之后,ARG变量将不再存在) |
配置指令 | FROM | 指定所创建镜像的基础镜像 |
配置指令 | LABEL | 为生成的镜像添加元数据标签信息(镜像描述信息) |
配置指令 | EXPOSE | 声明容器内服务监听的端口(仅声明,不会直接暴露端口) |
配置指令 | ENV | 指定镜像中的环境变量(镜像创建完之后,在镜像启动的容器中也会存在) |
配置指令 | ENTRYPOINT | 指定镜像的默认入口命令(与CMD类似,主要用于指定启动的父进程,PID=1) |
配置指令 | VOLUME | 创建挂载点, 将宿主机目录挂载到容器中 |
配置指令 | USER | 指定运行容器时的用户名或UID |
配置指令 | WORKDIR | 配置工作目录 |
配置指令 | ONBUILD | 创建子镜像时指定自动执行的操作指令 |
配置指令 | STOPSIGNAL | 指定容器退出时发送给PID=1进程的信号值 |
配置指令 | HEALTHCHECK | 配置所启动的容器如何进行健康检查 |
配置指令 | SHELL | 指定默认shell类型 |
操作指令 | RUN | 运行指定命令 |
操作指令 | CMD | 启动容器时指定默认执行的命令 |
操作指令 | ADD | 从构建宿主机复制文件到镜像中(tar文件会被解压) |
操作指令 | COPY | 从构建主机复制文件到镜像中 |
# 定义ARG KEY
ARG VERSION=3.0.1
# 使用ARG VALUE
LABEL VERSION_ID=${VERSION}
#构建容器时重新赋值ARG
docker build -t mynginx:v3.0.2 --build-arg VERSION=v3.0.2 .
ARG VERSION=9.3
FROM debian:${VERSION}
# 添加标签信息
LABEL version="l.0.0-rc3"
LABEL author="yeasy@github" date="2023-12-01"
LABEL description="This text illustrates\
that label-values can span multiple lines."
# 通过标签信息过滤镜像(区分大小写)
docker images --filter="label=author=service"
格式
作用
特别说明
样例
# 定义ENV 变量
ENV APP VERS工ON=l.0.0
ENV APP_HOME=/usr/local/app
ENV PATH $PATH:/usr/local/bin
# 容器运行时覆盖ENV变量
docker run -itd --name test2 --env key1=run_value1 mynginx:v3.0.2
VOLUME ["/data"] # [“/data”]可以是一个JsonArray ,也可以是多个值
VOLUME /var/log
VOLUME /var/log /opt
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
# 最终路径为 /a/b/c
格式
作用
特别说明
样例
#imageA Dockerfile
[...]
ONBUILD ADD . / app/src
ONBUILD RUN /usr/local/bin/python build --dir / app/src
[...]
#imageB Dockerfile
#等价于在imageA的Dockerfile添加如下命令
## . / app/src
## RUN /usr/ ocal/ bin python-bu ld --dir /app/src
FROM imageA
#格式1:根据所执行命令返回值是否为0来判断(0:成功; 1:失败; 2:保留)
HEALTHCHECK [OPTIONS] CMD command
#格式2: 禁止基础镜像中的健康检查
HEALTHCHECK NONE
# OPTIONS选项
## --interval=30:两次健康检查的间隔,默认为 30 秒;
## --timeout=30:健康检查命令运行的超时时间,超过视为失败,默认30秒;
## --retries=3:指定失败多少次视为unhealth,默认3次
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -fs http://localhost/ || exit 1 # 如果执行不成功返回1
#状态查看
[root@localhost nginx]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6720519218d9 mynginx:v3.0.4 "/docker-entrypoint.…" 14 seconds ago Up 12 seconds (healthy) 80/tcp test1
SHELL ["/bin/bash","-c"]
SHELL ["powershell", "-command"]
# 示例,比如在Windows时,默认shell是["CMD","/S","/C"]
# docker调用的是cmd /S /C powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
RUN powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
# exec格式这样写,虽然没有调用cmd.exe 但写起来比较麻烦。
# 所以可以通过SHELL ["powershell", "-command"] 这样省去前边的powershell -command
RUN ["powershell", "-command", "Execute-MyCmdlet", "-param1 \"c:\\foo.txt\""]
#语法1:exec 调用执行
ENTRYPOINT ["executable", "paraml ", "param2"]
#语法2:shell 中执行
ENTRYPOINT executable param1 param2
# Dockerfile CMD echo this is dockerfile cmd one CMD echo this is dockerfile cmd two CMD ["echo", "this is dockerfile cmd three"] ENTRYPOINT echo "this is dockerfile entrypoint shell" ENTRYPOINT ["echo", "this is dockerfile etnryponit exec"] # 构建镜像 docker build -t mynginx:v3.0.3 . # 运行新容器。根据输出结果可见(重点) ## 若使用exec的格式设置ENTRYPOINT指令,CMD指令的指定值将作为根命令的参数 ## 当指定多个ENTRYPOINT指令时, 只有最后一个起效 [root@localhost nginx]# docker run -it --name test1 mynginx:v3.0.3 this is dockerfile etnryponit exec echo this is dockerfile cmd three [root@localhost nginx]# ## 当CMD指令是shell格式,则ENTRYPOINT指令的参数会带上/bin/sh -c + CMD指令 [root@localhost nginx]# docker run -it --name test1 mynginx:v3.0.3 this is dockerfile etnryponit exec /bin/sh -c echo this is dockerfile cmd two [root@localhost nginx]# # 使用--entryponit 参数选项覆盖 ENTRYPOINT 指令 #注意: ## --entryponit后面只能接可执行命令, 并且不能带参数, 如果带参数会报错 ## --entrypoint的位置在镜像名称前面,如果在镜像名称后面会覆盖CMD指令内容 [root@localhost nginx]# docker run -it --name test2 --entrypoint=echo mynginx:v3.0.3 $$ 4207 [root@localhost nginx]# # 错误示范 ## --entryponit后面带命令参数 [root@localhost nginx]# docker run -it --name test3 --entrypoint="echo $$" mynginx:v3.0.3 docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "echo 4207": executable file not found in $PATH: unknown. [root@localhost nginx]# ## --entryponit 位置在镜像名称后面(覆盖的是CMD指令内容,而不是ENTRYPOINT指令内容) [root@localhost nginx]# docker run -it --name test4 mynginx:v3.0.3 --entrypoint="echo $$" this is dockerfile etnryponit exec --entrypoint=echo 4207 [root@localhost nginx]# ##ENTRYPOINT指定的进程pid=1 [root@localhost nginx]# docker run -it --name test5 --entrypoint=top ubuntu ..... PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 7292 1928 1384 R 0.0 0.0 0:00.04 top
# Dockerfile FROM alpine:3.4 ... RUN addgroup -S redis && adduser -S -G redis redis ... ENTRYPOINT ["docker-entrypoint.sh"] EXPOSE 6379 CMD [ "redis-server" ] # docker-entrypoint.sh (该脚本的内容就是根据 CMD 的内容来判断,如果是 redis-server 的话,则切换到 redis 用户身份启动服务器,否则依旧使用 root 身份执行) #!/bin/sh ... # allow the container to be started with `--user` if [ "$1" = 'redis-server' -a "$(id -u)" = '0' ]; then find . \! -user redis -exec chown redis '{}' + exec gosu redis "$0" "$@" fi exec "$@"
RUN apt-get update \
&& apt-get install -y libsnappy-dev zliblg-dev libbz2-dev \
&& rm -rf /var/cache/apt \
&& rm -rf /var/lib/apt/lists/*
#语法1, shell形式, 默认 /bin/sh -c运行
##1.1 此时运行为shell的子进程,能使用shell的操作符(if、环境变量、? *通配符等)
##1.2 注意:进程在容器中的 PID != 1,这意味着该进程并不能接受到外部传入的停止信号docker stop
CMD command param1 param2 ...
#语法2, exec形式
##2.1 不会以/bin/sh -c运行(非shell子进程),因此不支持shell的操作符
##2.2 若运行的命令依赖shell特性,可以手动启动CMD ["/bin/sh","-c","executable","param1"...]
CMD ["executable","param1","param2"]
#语法3, exec形式, 仅设置参数, 配合ENTRYPOINT使用, 作为 ENTRYPOINT的默认参数
CMD ["param1", "param2"]
# Dockerfile
CMD echo this is dockerfile cmd one
CMD echo this is dockerfile cmd two
CMD echo this is dockerfile cmd three
# docker image inspect输出(默认/bin/sh -c运行;只有最后一个CMD生效)
"Cmd": [
"/bin/sh",
"-c",
"echo this is dockerfile cmd three"
]
# docker run 覆盖CMD指令
[root@localhost nginx]# docker run -it --name test1 mynginx:v3.0.3 echo "this is docker run override CMD"
this is docker run override CMD
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 [“p1_cmd”,“p2_cmd”] | p1_cmd p2_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry p1_cmd p2_cmd |
CMD exec_cmd p1_cmd | exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd |
# 错误案例
## 1. COPY的src不在Dockerfile所在目录或子目录下
COPY /home/hyp/workspace/demo/test.c src
## ERROR: failed to solve: failed to compute cache key: failed to calculate checksum of ref 8584a5bb-281d-45d1-85da-b525e319a629::l67260bvxak2j3ikf8lez82tu: failed to walk /var/lib/docker/tmp/buildkit-mount160530273/home/hyp/workspace/demo: lstat /var/lib/docker/tmp/buildkit-mount160530273/home/hyp/workspace/demo: no such file or directory
## 2. 指定多个src,但是dest没有以 / 结尾
COPY demo/test.py demo/test.c target
## 因为dest没有以 / 结尾,被当作普通文件处理。上述命令最终的效果是最后一个src被复制成target文件。
# 正确案例
COPY demo/test.py demo/test.c dest/
# demo.tar 将解压成demo目录到dest目录下 (即 dest/demo/)
ADD demo.tar dest/
OPTIONS说明:
-f :指定返回值的模板文件。
-s :显示总的文件大小。
--type :为指定类型返回JSON。
[root@localhost nginx]# docker inspect test1 [ { "Id": "a87510fecc9a1987de5f75521a1322b417efe684499df88bc2886be39cf38193", "Created": "2024-03-06T07:21:07.908834446Z", "Path": "/docker-entrypoint.sh", "Args": [ "nginx", "-g", "daemon off;" ], "State": { "Status": "running", "Running": true, "Paused": false, "Restarting": false, "OOMKilled": false, "Dead": false, "Pid": 12805, "ExitCode": 0, "Error": "", "StartedAt": "2024-03-06T07:21:08.406050451Z", "FinishedAt": "0001-01-01T00:00:00Z", "Health": { "Status": "healthy", "FailingStreak": 0, "Log": [ { "Start": "2024-03-06T16:33:25.6583247+08:00", "End": "2024-03-06T16:33:25.922296207+08:00", "ExitCode": 0, "Output": "1024\n" } .... ] } }, "Image": "sha256:3d8a72e2e67e99b1aea5bcec45eb5e83f4bfe31d36db9011a22919647d364b8e", "ResolvConfPath": "/var/lib/docker/containers/a87510fecc9a1987de5f75521a1322b417efe684499df88bc2886be39cf38193/resolv.conf", "HostnamePath": "/var/lib/docker/containers/a87510fecc9a1987de5f75521a1322b417efe684499df88bc2886be39cf38193/hostname", "HostsPath": "/var/lib/docker/containers/a87510fecc9a1987de5f75521a1322b417efe684499df88bc2886be39cf38193/hosts", "LogPath": "/var/lib/docker/containers/a87510fecc9a1987de5f75521a1322b417efe684499df88bc2886be39cf38193/a87510fecc9a1987de5f75521a1322b417efe684499df88bc2886be39cf38193-json.log", "Name": "/test1", "RestartCount": 0, "Driver": "overlay2", "Platform": "linux", "MountLabel": "", "ProcessLabel": "", "AppArmorProfile": "", "ExecIDs": null, .... "Config": { "Hostname": "a87510fecc9a", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "ExposedPorts": { "80/tcp": {} }, "Tty": true, "OpenStdin": true, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "NGINX_VERSION=1.25.4", "NJS_VERSION=0.8.3", "PKG_RELEASE=1~bookworm", "key1=value1", "key2=value2 key3 value3" ], "Cmd": [ "nginx", "-g", "daemon off;" ], "Healthcheck": { "Test": [ "CMD-SHELL", "echo 1024" ], "Interval": 5000000000, "Timeout": 3000000000 }, "Image": "mynginx:v3.0.4", "Volumes": null, "WorkingDir": "", "Entrypoint": [ "/docker-entrypoint.sh" ], "OnBuild": null, "Labels": { "AUTHOR": "hyp@dgzq.com.cn", "DATE": "20231206", "VERSION_ID": "3.0.3", "maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>" }, "StopSignal": "SIGQUIT" }, ... } ]
Placeholder | Description |
---|---|
.ID | Image ID |
.Repository | Image repository |
.Tag | Image tag |
.Digest | Image digest |
.CreatedSince | Elapsed time since the image was created |
.CreatedAt | Time when the image was created |
.Size | Image disk size |
示例
$ docker images --format "{{.ID}}: {{.Repository}}"
77af4d6b9913: <none>
b6fa739cedf5: committ
78a85c484f71: <none>
$ docker images --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"
IMAGE ID REPOSITORY TAG
77af4d6b9913 <none> <none>
b6fa739cedf5 committ latest
78a85c484f71 <none> <none>
$ docker images --format json
{"Containers":"N/A","CreatedAt":"2021-03-04 03:24:42 +0100 CET","CreatedSince":"5 days ago","Digest":"\u003cnone\u003e","ID":"4dd97cefde62","Repository":"ubuntu","SharedSize":"N/A","Size":"72.9MB","Tag":"latest","UniqueSize":"N/A","VirtualSize":"72.9MB"}
{"Containers":"N/A","CreatedAt":"2021-02-17 22:19:54 +0100 CET","CreatedSince":"2 weeks ago","Digest":"\u003cnone\u003e","ID":"28f6e2705743","Repository":"alpine","SharedSize":"N/A","Size":"5.61MB","Tag":"latest","UniqueSize":"N/A","VirtualSize":"5.613MB"}
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 3d8a72e2e67e 2 days ago 187MB
<none> <none> ba9c646b273b 2 days ago 187MB
<none> <none> 68a539de5f3a 2 days ago 187MB
[root@localhost demo]# docker history mynginx:v3.0.4 IMAGE CREATED CREATED BY SIZE COMMENT 1439d3105e94 2 days ago ADD demo.tar dest/ # buildkit 901B buildkit.dockerfile.v0 <missing> 2 weeks ago HEALTHCHECK &{["CMD-SHELL" "echo 1024"] "5s"… 0B buildkit.dockerfile.v0 <missing> 2 weeks ago RUN |1 VERSION=3.0.3 /bin/sh -c echo "this i… 29B buildkit.dockerfile.v0 <missing> 2 weeks ago RUN |1 VERSION=3.0.3 /bin/sh -c echo "${VERS… 6B buildkit.dockerfile.v0 <missing> 2 weeks ago ENV key1=value1 key2=value2 key3 value3 0B buildkit.dockerfile.v0 <missing> 2 weeks ago ENV key1=value2 key3 value3 0B buildkit.dockerfile.v0 <missing> 2 weeks ago LABEL AUTHOR=hyp@dgzq.com.cn DATE=20231206 0B buildkit.dockerfile.v0 <missing> 2 weeks ago LABEL VERSION_ID=3.0.3 0B buildkit.dockerfile.v0 <missing> 2 weeks ago ARG VERSION=3.0.3 0B buildkit.dockerfile.v0 <missing> 3 weeks ago CMD ["nginx" "-g" "daemon off;"] 0B buildkit.dockerfile.v0 <missing> 3 weeks ago STOPSIGNAL SIGQUIT 0B buildkit.dockerfile.v0 <missing> 3 weeks ago EXPOSE map[80/tcp:{}] 0B buildkit.dockerfile.v0 <missing> 3 weeks ago ENTRYPOINT ["/docker-entrypoint.sh"] 0B buildkit.dockerfile.v0 <missing> 3 weeks ago COPY 30-tune-worker-processes.sh /docker-ent… 4.62kB buildkit.dockerfile.v0 <missing> 3 weeks ago COPY 20-envsubst-on-templates.sh /docker-ent… 3.02kB buildkit.dockerfile.v0 <missing> 3 weeks ago COPY 15-local-resolvers.envsh /docker-entryp… 336B buildkit.dockerfile.v0 <missing> 3 weeks ago COPY 10-listen-on-ipv6-by-default.sh /docker… 2.12kB buildkit.dockerfile.v0 <missing> 3 weeks ago COPY docker-entrypoint.sh / # buildkit 1.62kB buildkit.dockerfile.v0 <missing> 3 weeks ago RUN /bin/sh -c set -x && groupadd --syst… 112MB buildkit.dockerfile.v0 <missing> 3 weeks ago ENV PKG_RELEASE=1~bookworm 0B buildkit.dockerfile.v0 <missing> 3 weeks ago ENV NJS_VERSION=0.8.3 0B buildkit.dockerfile.v0 <missing> 3 weeks ago ENV NGINX_VERSION=1.25.4 0B buildkit.dockerfile.v0 <missing> 3 weeks ago LABEL maintainer=NGINX Docker Maintainers <d… 0B buildkit.dockerfile.v0 <missing> 3 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B <missing> 3 weeks ago /bin/sh -c #(nop) ADD file:eb6a3def1f69e7665… 74.8MB
- 该命令将读取指定路径下(包括子目录)的 Dockerfile ,并将该路径下所有数据作为上下文( Context )发送给 Docker 服务端。Docker 服务端在校验 Dockerfile 格式通过后,逐条执行其中定义的指令,碰到 ADD、COPY、RUN 指令会生成一层新的镜像 。最终如果创建镜像成功,会返回最终镜像的ID。
- 如果上下文过大, 会导致发送大量数据给服务端,延缓创建过程。除非是生成镜像所必需的文件,不然不要放到上下文路径。如果使用非上下文路径下的 Dockerfile,可以通过 -f 选项来指定其路径。
- 要指定生成镜像的标签信息,可以通过 t 选项。该选项可以重复使用多次为镜像一次添加多个名称。例如,上下文路径为 /tmp/docker_builder/,并且希望生成镜像标签为 builder/first_image: 1.0.0, 可以使用下面的命令:
docker build -t builder/first_image:1.0.0 /tmp/docker_builder/
Option | Default | Description |
---|---|---|
–add-host | Add a custom host-to-IP mapping (host:ip) | |
–build-arg | Set build-time variables | |
–cache-from | Images to consider as cache sources | |
–cgroup-parent | Set the parent cgroup for the instructions during buildRUN | |
–compress | Compress the build context using gzip | |
–cpu-period | Limit the CPU CFS (Completely Fair Scheduler) period | |
–cpu-quota | Limit the CPU CFS (Completely Fair Scheduler) quota | |
-c, --cpu-shares | CPU shares (relative weight) | |
–cpuset-cpus | CPUs in which to allow execution (0-3, 0,1) | |
–cpuset-mems | MEMs in which to allow execution (0-3, 0,1) | |
–disable-content-trust | true | Skip image verification |
-f, --file | Name of the Dockerfile (Default is PATH/Dockerfile) | |
–force-rm | Always remove intermediate containers | |
–iidfile | Write the image ID to the file | |
–isolation | Container isolation technology | |
–label | Set metadata for an image | |
-m, --memory | Memory limit | |
–memory-swap | Swap limit equal to memory plus swap: -1 to enable unlimited swap | |
–network | API 1.25+ Set the networking mode for the RUN instructions during build | |
–no-cache | Do not use cache when building the image | |
–platform | API 1.38+ Set platform if server is multi-platform capable | |
–pull | Always attempt to pull a newer version of the image | |
-q, --quiet | Suppress the build output and print image ID on success | |
–rm | true | Remove intermediate containers after a successful build |
–security-opt | Security options | |
–shm-size | Size of /dev/shm | |
–squash | API 1.25+ experimental (daemon) Squash newly built layers into a single new layer | |
-t, --tag | Name and optionally a tag in the formatname:tag | |
–target | Set the target build stage to build. | |
–ulimit | Ulimit options |
# 构建一个运行在一个我自己剪裁过的Centos7基础系统二进制包上的 Java8 镜像 FROM scratch ADD centos-7-x86_64-docker.tar.xz / RUN yum install -y wget && \ yum clean all && \ ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \ echo "Asia/Shanghai" > /etc/timezone ENV JAVA_VERSION jdk1.8.0_271 ENV JAVA_HOME /usr/lib/${JAVA_VERSION} ENV PATH ${JAVA_HOME}/bin:$PATH # 涉及改变镜像大小的指令,尽量放到同一行,这样构建过程中的删除指令对减小体积才能生效 RUN wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" \ http://download.oracle.com/otn-pub/java/jdk/8u271-b09/61ae65e088624f5aaa0b1d2d801acb16/jdk-8u271-linux-x64.tar.gz -O /usr/lib/jdk-8u271-linux-x64.tar.gz && \ tar -xf /usr/lib/jdk-8u271-linux-x64.tar.gz -C /usr/lib/ && \ rm -rf /usr/lib/jdk-8u271-linux-x64.tar.gz && \ rm -rf ${JAVA_HOME}/src.zip \ ${JAVA_HOME}/lib/visualvm \ ${JAVA_HOME}/jre/lib/plugin.jar \ ${JAVA_HOME}/jre/bin/javaws \ ${JAVA_HOME}/jre/lib/desktop \ ${JAVA_HOME}/jre/plugin \ ${JAVA_HOME}/jre/lib/deploy* \ ${JAVA_HOME}/jre/lib/amd64/libglass.so \ ${JAVA_HOME}/jre/lib/amd64/libgstreamer-lite.so \ ${JAVA_HOME}/jre/lib/amd64/libjavafx*.so \ ${JAVA_HOME}/jre/lib/amd64/libjfx*.so CMD ['/bin/bash']
# dockerignore 文件中可以定义忽略模式
*/temp*
*/*/temp*
tmp?
-*
Dockerfile
!README.md
# 1. main.go # Go 语言应用为例 创建干净目录,进入到目录中,创建 main.go文件,内容为: package main import ( "fmt" ) func main() { fmt.Println("Hello, Docker") } # 2. Dockerfile # 创建 Dockerfile ,使用 go ang :l .9 镜像编译应用二进制文件为 ,使用精简的镜像 alpine:latest 作为运行环境。 Dockerfile完整内容为: FROM golang:l.9 as builder # define stage name as builder RUN mkdir -p /go/src/test WORKDIR /go/src/test COPY main.go . RUN CGO_ENABLED=O GOOS=linux go build -o app . FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /root/ COPY --from=builder /go/src/test/app . # copy file from the builder stage CMD ["./app"] # 执行如下命令创建镜像,并运行应用: docker build -t test-multistage:latest . # 查看生成的最终镜像(最终大小仅6.55MB) docker images | grep test-multistage
编写 Dockerfile 时,通常使⽤⼀个通⽤的容器镜像作为基础镜像,例如: eclipse-temurin:8-alpine ,选⽤最⼩化基础镜像,即只包含项⽬确实需要的系统⼯具和库的镜像,较⼩的基础镜像可以确保在⼀个新节点上拉起容器时有更快的启动时间(节省了从镜像仓库拉取镜像的⽹络请求时间),并且能够最⼩化系统的攻击⾯,确保所⽤的操作系统是安全的,⼀般推荐采⽤以 alpine 系统为基础的基础镜像。
为了降低复杂性、减少依赖、减少安全⻛险、减⼩镜像⽂件⼤⼩、节约构建时间,应该避免构建镜像过程中安装任何不必要的包,例如:不需要在应⽤镜像内包含⽂本编辑器(vim)等。
尽管单个容器确实可以运⾏多个应⽤程序,但出于以下原因,需要尽可能考虑遵循“每个容器⼀个应⽤程序“(以下简称单进程容器)的最佳实践:
使⽤ Dockerfile 构建镜像时建议将 Dockerfile 放置⼀个新的空⽬录下,将构建所需要的⽂件添加到该⽬录中,为 了提⾼构建镜像的效率,可以在该⽬录下新建⼀个 .dockerignore ⽂件来指定要忽略的⽂件和目录。 .dockerignore ⽂件的排除模式语法和 git 的 .gitignore ⽂件相似。
构建镜像时,Dockerfile 的每⼀条 RUN 指令都会在镜像上构建⼀层,为了减⼩镜像⽂件⼤⼩,建议在 Dockerfile可读性(也包括⻓期的可维护性)和减⼩层数之间做⼀个平衡,⽐如,将多个 RUN 指令进⾏合并执⾏(通过 &&符串连多条 shell 命令),可有效减少镜像的层数。
镜像的构建过程中,会顺序执⾏ Dockerfile 中的指令,在执⾏每条指令之前,会先从缓存中查找是否已经存在可重 ⽤的镜像,如果有就使⽤现存的镜像,不再重复创建,以加快镜像构建过程。如果不想在构建过程中使⽤缓存,可 在 docker build 命令中使⽤ --no-cache=true 选项,镜像缓存的基本规则包含:
当⼀个容器被销毁(即停⽌运⾏)时,操作系统会发送 SIGTERM 给容器内的1号进程(pid=1,可通过 ps -ef 命令查看),1号进程接收到信号后可进⾏容器终⽌前的资源释放等处理操作。 例如:构建镜像时,可利⽤系统的 exec 命令特性,为应⽤启动编写独⽴的 shell 脚本⽂件,以 exec 形式启动相关进程。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。