Docker Dockerfile 篇
Dockerfile 文本文件是创建 Docker 镜像的基础,
其中包含一系列指令,用于描述如何构建 Docker 镜像。
每条指令创建镜像中的一层,并执行相应的操作,如安装软件、设置环境变量、复制文件等。
FROM
指定基础镜像
FROM <image>[:<tag>] [AS <name>]
<image>:镜像名[:<tag>]:镜像标签,可选[AS <name>]:别名,可选,多步骤时可用
如:
FROM golang:1.22.4 AS build_base
以golang的1.22.4版本作为构建基础
WORKDIR
设置工作目录,所有后续指令都在该目录中执行
WORKDIR /path/to/directory
如:
WORKDIR /build
COPY
将文件从宿主机复制到镜像内
COPY <src> <dest>
<src>:源<dest>:目标
如:COPY go.mod . COPY . .将
go.mod复制到工作目录下
将.目录下的内容全部复制到工作目录下
--from
在 Docker 多阶段构建(multi-stage builds)中,
COPY 指令可以使用 --from 选项来将文件从前一个构建阶段中复制到当前阶段。
这种方式常用于减少镜像大小,只复制最终所需的文件,而不是将整个构建环境带入最终镜像。
如:
# 第二步
FROM build_base AS builder
...略
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /root/main ./main.go
# 第三步
FROM alpine:latest as runner
WORKDIR /root
COPY --from=builder /root/main .
这里将构建第二阶段编译得到的二进制main文件,复制到了当前工作目录下。
RUN
在容器内执行命令。构建时运行。执行指令的结果会保存在镜像中。
RUN <cmd>
如:
RUN go env -w GO111MODULE=on
RUN go env -w GOPROXY=https://goproxy.cn,direct
RUN go mod download
ARG
定义构建时的变量,docker build期间可用,不会保留在构建的镜像中。
ARG key=value
指令中传参
docker build 命令时使用 --build-arg 可以传递参数
首先编写dockerfile:
因为arg只在build期间可用,想要在运行容器时使用到,需要将其设为环境变量
# CMD 被覆盖的例子
FROM redis:latest
ARG svc
RUN echo $svc
ENV ESVC="ENV:"+$svc
CMD "echo" $ESVC
构建容器:
在构建的过程中会执行RUN的指令,输出传入的参数
docker build --build-arg svc=服务名是xxx -t arg_test:1 .
...... 0.0s
=> [2/2] RUN echo 服务名是xxx 0.1s
......
运行容器:
执行CMD,输出环境变量
docker run --name arg_t arg_test:1
ENV:+服务名是xxx
在docker-compose中传参
传入参数的层级是
services:
service_name:
build:
args:
svc: "服务名"
ENV
设置环境变量
VOLUME
定义挂载点,将容器中的目录或文件标记为挂载点,便于宿主机持久化数据
VOLUME [""]
如:
VOLUME /usr/share/nginx/html
可见 VOLUME 的参数中并没有指定存储在宿主机上的具体目录,其需要在启动容器时使用 -v 设置挂载点,
作用:
- 默认持久化数据,
即使用户运行容器时没有手动设置挂载点,数据仍会持久化到Docker管理的卷中,不会随容器删除而丢失。
可以使用docker volume ls查看挂载点列表 - 文档化意图
可以明确的告诉其他人,某些目录是重要的,应该被持久化。CMD
指定容器启动时要执行的默认命令,该命令可以在运行容器时被覆盖。
CMD <cmd>
如:
CMD ["echo", "Hello from the Dockerfile!"]
被覆盖
首先有个dockerfile,
# CMD 被覆盖的例子
FROM redis:latest
CMD ["echo", "Hello from the Dockerfile!"]
构建这个镜像 cover_test ,使用CMD输出一段文字。
docker build -t cover_test:1 .
启动容器,一次不提供指令,一次提供指令
docker run --name cover_t cover_test:1
Hello from the Dockerfile!
docker run --name cover_t2 cover_test:1 echo 你好,CMD被覆盖了
你好,CMD被覆盖了
如此可见,原指令被覆盖
ENTRYPOINT
类似于 CMD,用于指定容器启动时要执行的命令。
与 CMD 不同,ENTRYPOINT 不会被 docker run 命令行参数覆盖,
而是将参数传递给 ENTRYPOINT 指定的命令。
ENTRYPOINT ["echo", "Hello"]
尝试添加其他指令:
FROM redis:latest
ENTRYPOINT ["echo", "Hello"]
构建镜像&运行
docker build -t entrypoint:1 .
docker run entrypoint:1 Fan的小破站 fanfine.cn
Hello Fan的小破站 fanfine.cn
可见,ENTRYPOINT 中的 Hello 没有被覆盖,仅是被追加在Hello的后面
注意,如果去掉了中括号 [],
ENTRYPOINT "echo" "Hello"
那么追加参数会出现下面的现象,
docker run entrypoint:1 Fan的小破站 fanfine.cn
Hello
因为附加参数没有作为 ENTRYPOINT 的参数
其他
- ONBUILD
设置一个触发器,当使用当前镜像作为基础镜像时,ONBUILD 指令定义的命令会被执行。 - HEALTHCHECK
定义容器的健康检查命令,用于确定容器是否处于正常运行状态。 - STOPSIGNAL
指定容器停止时发送的系统信号,默认为 SIGTERM。 - SHELL
指定容器内执行 RUN 命令时使用的 shell 程序。默认是 /bin/sh。 - LABEL
为镜像添加元数据,通常用于描述镜像的作者、版本等信息。 - USER
设置接下来运行的命令或脚本的用户身份。如果没有指定,默认使用 root 用户。