Dockerfile详解

Dockerfile 核心指令说明

指令作用执行阶段示例注意事项
FROM指定基础镜像构建阶段

FROM ubuntu:22.04 

必须为Dockerfile的第一个指令;支持多阶段构建中多次使用;scratch表示空镜像
RUN执行命令并创建新的镜像层构建阶段

RUN apt-get update && apt-get install -y nginx 

 RUN ["apt-get", "install", "-y", "nginx"]

推荐使用exec格式(JSON数组)避免shell注入风险;合并多个命令减少镜像层数;清理缓存命令放同一层
COPY复制本地文件/目录到镜像构建阶段

COPY app.py /app/ 

 COPY ["src/*.py", "/app/"]

仅复制文件,不支持URL和自动解压;目标路径不存在会自动创建;使用.dockerignore排除不需要的文件
ADD复制文件/目录或远程URL文件到镜像构建阶段

ADD https://example.com/file.tar.gz /tmp/ 

支持自动解压tar.gz文件和URL下载;优先使用COPY(更明确);远程URL文件不会自动解压
CMD指定容器启动命令运行阶段CMD ["nginx", "-g", "daemon off;"] 每个Dockerfile只能有一个CMD,多个则最后一个生效;可被docker run命令参数覆盖;通常用于设置默认参数
ENTRYPOINT设置容器入口点运行阶段ENTRYPOINT ["nginx"] <br> ENTRYPOINT nginx不可被docker run命令直接覆盖(需使用--entrypoint选项);常与CMD配合使用(CMD作为参数)
ENV设置环境变量构建+运行阶段

ENV APP_HOME=/app 

 ENV PATH=$PATH:/usr/local/bin

环境变量在构建和运行时均可用;可通过docker run -e覆盖;使用ENV key=value格式,等号前后无空格
WORKDIR设置工作目录构建+运行阶段

WORKDIR /app

WORKDIR /usr/local/nginx

后续指令的工作目录;若不存在会自动创建;推荐使用绝对路径;可多次使用切换目录
EXPOSE声明容器运行时监听的端口构建阶段(声明)

EXPOSE 80/tcp

EXPOSE 443/udp

仅为文档说明,不实际映射端口;需通过docker run -p实际映射;可指定协议(tcp/udp)
VOLUME创建匿名卷构建+运行阶段

VOLUME ["/data"] 

 VOLUME /var/log

运行时会自动创建匿名卷,避免数据丢失;无法指定宿主机路径(运行时通过-v指定)
ARG定义构建参数构建阶段

ARG VERSION=1.0

 ARG USER=builder

仅在构建时可用,运行时不可访问;可通过docker build --build-arg覆盖;默认值可选
LABEL添加镜像元数据构建阶段LABEL maintainer="dev@example.com" version="1.0" 键值对格式,可包含多个标签;使用OCI标准标签提高兼容性;通过docker inspect查看
ONBUILD设置子镜像构建触发器构建阶段(子镜像)ONBUILD COPY . /app <br> ONBUILD RUN npm install当当前镜像被用作其他镜像的基础镜像时触发;避免在基础镜像中过度使用
HEALTHCHECK定义容器健康检查命令运行阶段`HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost/
SHELL更改默认shell构建阶段SHELL ["/bin/sh", "-c"] <br> SHELL ["powershell", "-Command"]Windows容器常用;影响RUN/CMD/ENTRYPOINT的shell模式执行;默认Linux为["/bin/sh", "-c"]
USER指定运行用户构建+运行阶段

USER www-data

USER 1000:1000

需确保用户已存在(可通过RUN创建);切换后后续指令均使用该用户;降低权限增强安全性
STOPSIGNAL设置容器停止信号运行阶段STOPSIGNAL SIGTERM <br> STOPSIGNAL 15默认为SIGTERM;指定容器接收的停止信号;与应用程序信号处理机制配合使用
AS为多阶段构建中的阶段命名构建阶段

FROM node:18 AS builder

FROM alpine:latest AS runner

配合多阶段构建使用;通过--from=builder引用其他阶段文件;减少最终镜像大小

docker build -t myalpine:v1.0 -f Dockerfile . --progress=plain --no-cache

--progress=plain 是一个控制构建输出日志显示格式的选项

 --no-cache:强制重新执行所有步骤(不利用缓存)

RUN:   镜像构建阶段

CMD:镜像运行阶段

指令测试

RUN指令

1. 准备Dockerfile指令

    

-c 非交互模式

2.build镜像

docker build -t run-test:v1.0 -f Dockerfile . --progress=plain --no-cache

    

  1. 在build中,执行了RUN指令
  2.  RUN [ "echo","docker构建阶段成功-execV1"," $APP_NAME" ] 存在bug,无法使用env变量
  3. CMD中的未打印出结果,表示CMD没有在构建阶段执行

3.启动镜像

# docker run -it --name run-container run-mirror:v0.0.1

ARG指令

作用:定义变量,build构建时使用的变量

 docker build   --build-arg  #修改变量

  

使用默认值

build时自定义ARG参数值

  

使用场景

 自定义基础镜像版本

# 自定义镜像版本(默认最新版本)
ARG version=latest
FROM alpine:${version}

自定义用户名

自定义路径 

ENV指令

一般容器运行时使用,可通过

 docker run -e  启动镜像时修改环境变量

查询所有的环境变量

docker image inspect  容器名称

USER指令

使用root账号有风险,设置一个账号专门管理

多阶段构建示例

# 构建阶段 
FROM maven:3.8-openjdk-17 AS builder 
WORKDIR /app 
COPY pom.xml . COPY src ./src 
RUN mvn package -DskipTests  



# 运行阶段 
FROM openjdk:17-jdk-slim 
WORKDIR /app 
COPY --from=builder /app/target/*.jar app.jar 
EXPOSE 8080 
ENTRYPOINT ["java", "-jar", "app.jar"]

RUN

CMD

Dockerfile 是用于构建 Docker 镜像的文本文件,其中包含了按顺序执行的一系列指令。每个指令都会在镜像中创建一个新的层,这使得 Docker 镜像具有分层的结构,可以高效地利用存储空间并加快构建速度[^1]。 ### Dockerfile 的基本结构 Dockerfile 通常由以下几个部分组成: - **基础镜像信息**:使用 `FROM` 指令指定。 - **维护者信息**:可选,使用 `LABEL` 或 `MAINTAINER` 指令指定。 - **镜像操作指令**:如 `RUN`、`COPY`、`ADD` 等,用于对镜像进行操作。 - **容器启动命令**:如 `CMD`、`ENTRYPOINT`,用于指定容器启动时运行的命令。 - **其他配置指令**:如 `WORKDIR`、`ENV`、`EXPOSE`、`VOLUME` 等,用于设置容器的工作环境。 ### Dockerfile 指令详解 #### `FROM` `FROM` 指令用于指定基础镜像,这是 Dockerfile 的第一条指令,并且每个 Dockerfile 至少要有一个 `FROM` 指令。可以指定标签来选择特定版本的基础镜像,也可以使用 `AS` 关键字为构建阶段命名,常用于多阶段构建[^3]。 ```dockerfile FROM ubuntu:20.04 ``` #### `ARG` `ARG` 指令用于定义构建时的变量,可以在构建镜像时通过 `--build-arg` 参数传递值。这些变量可以在 Dockerfile 中被 `RUN` 指令等引用[^2]。 ```dockerfile ARG VERSION=1.0 RUN echo "Version: $VERSION" ``` #### `ENV` `ENV` 指令用于设置环境变量,这些变量在构建过程中以及容器运行时都可用。环境变量可以通过 `$VAR` 的形式在 Dockerfile 中引用。 ```dockerfile ENV MY_PATH /usr/local/myapp WORKDIR $MY_PATH ``` #### `COPY` `COPY` 指令用于将本地文件系统中的文件或目录复制到镜像中的指定路径。支持从构建阶段复制文件(多阶段构建)[^3]。 ```dockerfile COPY . /app ``` #### `WORKDIR` `WORKDIR` 指令用于设置工作目录。后续的 `RUN`、`CMD`、`ENTRYPOINT` 等指令都会在这个目录下执行。如果目录不存在,会被自动创建[^4]。 ```dockerfile WORKDIR /app ``` #### `RUN` `RUN` 指令用于在镜像构建过程中执行命令。这些命令通常用于安装软件包或编译代码[^1]。 ```dockerfile RUN apt-get update && apt-get install -y nginx ``` #### `CMD` `CMD` 指令用于指定容器启动时默认执行的命令。如果有多个 `CMD` 指令,只有最后一个会生效。`CMD` 提供的默认参数可以在运行容器时被覆盖。 ```dockerfile CMD ["nginx", "-g", "daemon off;"] ``` #### `ENTRYPOINT` `ENTRYPOINT` 指令用于配置容器启动时运行的可执行文件。与 `CMD` 不同的是,`ENTRYPOINT` 的参数不会被覆盖,而是将 `CMD` 或运行时提供的参数作为其参数。 ```dockerfile ENTRYPOINT ["nginx", "-g"] CMD ["daemon off;"] ``` #### `LABEL` `LABEL` 指令用于为镜像添加元数据,如版本号、描述等信息。这些标签可以通过 `docker inspect` 命令查看[^2]。 ```dockerfile LABEL version="1.0" LABEL description="This is a sample Dockerfile" ``` #### `EXPOSE` `EXPOSE` 指令用于声明容器运行时监听的端口。虽然它不会自动映射端口,但可以作为文档说明,帮助用户了解容器需要暴露哪些端口[^1]。 ```dockerfile EXPOSE 80 ``` #### `VOLUME` `VOLUME` 指令用于创建挂载点,使数据可以在容器之间共享或持久化。即使容器停止或删除,卷中的数据仍然存在[^4]。 ```dockerfile VOLUME ["/data"] ``` #### `USER` `USER` 指令用于指定运行容器时使用的用户。这有助于提高安全性,避免以 root 用户身份运行容器。 ```dockerfile USER myuser ``` #### `ONBUILD` `ONBUILD` 指令用于设置一个触发器,当该镜像被其他镜像作为基础镜像时,这些触发器会在子镜像构建时自动执行。这对于构建依赖于父镜像的子镜像非常有用。 ```dockerfile ONBUILD COPY . /app ONBUILD RUN make /app ``` ### 多阶段构建 多阶段构建允许在一个 Dockerfile 中使用多个 `FROM` 指令,每个 `FROM` 指令定义一个独立的构建阶段。通过这种方式,可以在一个阶段中编译代码,在另一个阶段中仅包含运行所需的文件,从而减少最终镜像的大小。 ```dockerfile # 第一阶段:构建阶段 FROM golang:1.18 AS builder WORKDIR /app COPY . . RUN go build -o myapp # 第二阶段:运行阶段 FROM alpine:latest WORKDIR /app COPY --from=builder /app/myapp . CMD ["./myapp"] ``` ### 最佳实践 - **最小化镜像大小**:尽量使用轻量级的基础镜像(如 Alpine Linux),并清理不必要的文件和缓存。 - **合理使用缓存**:Docker 在构建镜像时会利用缓存来加速构建过程。为了充分利用缓存,应将不经常变化的指令放在前面。 - **安全性和权限管理**:避免以 root 用户身份运行容器,使用 `USER` 指令指定非特权用户。 - **多阶段构建**:利用多阶段构建减少最终镜像的体积,只保留必要的文件和依赖项。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值