一、Dockerfile
没有 Dockerfile 时,构建镜像通常依赖人工操作:手动运行一个容器,在里面装软件、配环境、调参数,最后再手动提交成镜像。这个过程既繁琐,又难以复现。
而 Dockerfile 把这一系列操作全都写成了代码:
Dockerfile 的每一行都对应容器里的一个操作步骤,这使得镜像构建变得可版本化、可复用、可自动化。
二、Dockerfile 的基本结构
Dockerfile 通常遵循以下结构:
# 1. 基础镜像(起点) FROM python:3.9-slim # 2. 元数据信息(作者) LABEL maintainer="your-email@example.com" # 3. 设置工作目录 WORKDIR /app # 4. 复制文件 COPY requirements.txt . # 5. 安装依赖 RUN pip install --no-cache-dir -r requirements.txt # 6. 复制应用代码 COPY . . # 7. 声明运行端口 EXPOSE 8080 # 8. 设置容器启动命令 CMD ["python", "app.py"]三、常用指令
1.FROM:指定基础镜像(必须)
FROM是 Dockerfile 的第一条指令,它指定了当前镜像基于哪个现有镜像来构建。
# 基础镜像格式 FROM <image>[:<tag>] # 示例 FROM ubuntu:22.04 FROM python:3.9-slim FROM openjdk:17-alpine FROM node:18-alpine # 多阶段构建中的多个 FROM FROM golang:1.19 AS builder FROM alpine:latest2.WORKDIR:设置工作目录
WORKDIR设置了容器内的当前工作目录。如果目录不存在,Docker 会自动创建。
WORKDIR /app WORKDIR /usr/src/app WORKDIR /home/root3.RUN:执行命令(构建时)
RUN在镜像构建阶段执行命令,通常用于安装软件包、创建目录等。
# 单行命令 RUN apt-get update && apt-get install -y curl # 多行命令(用 \ 换行) RUN apt-get update && \ apt-get install -y python3 python3-pip && \ rm -rf /var/lib/apt/lists/* # 清理缓存以减小镜像体积 RUN pip install --no-cache-dir -r requirements.txt4.COPYvsADD:复制文件
| 指令 | 说明 | 建议 |
|---|---|---|
COPY | 复制文件或目录到容器 | 推荐,行为明确 |
ADD | 功能更多,支持解压和 URL 下载 | 仅在需要自动解压时使用 |
# COPY 用法 COPY requirements.txt . COPY . /app COPY --chown=user:group file.txt /app/ # ADD 用法(支持自动解压) ADD app.tar.gz /app/ ADD https://example.com/file.txt /tmp/5.ENV:设置环境变量
ENV用于设置容器内的环境变量,会同时存在于构建和运行阶段。
ENV PYTHONUNBUFFERED=1 ENV DB_HOST=localhost ENV DB_PORT=3306 ENV APP_ENV=production6.ARG:构建参数
ARG是构建时的参数,只在构建阶段有效。
ARG VERSION=latest FROM ubuntu:${VERSION} ARG APP_PORT=8080 ENV APP_PORT=${APP_PORT}# 构建时传入参数 docker build --build-arg VERSION=22.04 -t myapp .7.EXPOSE:声明端口
EXPOSE声明容器运行时监听的端口,仅作为文档性说明,真正的端口映射由-p参数完成。
EXPOSE 8080 EXPOSE 80 4438.CMDvsENTRYPOINT:容器启动命令
这两个指令都用于定义容器启动时执行的命令,但用途不同:
| 指令 | 特点 | 适用场景 |
|---|---|---|
CMD | 可以被docker run的命令覆盖 | 提供默认参数 |
ENTRYPOINT | 不可被覆盖 | 固定容器执行内容 |
# CMD 用法 CMD ["python", "app.py"] CMD python app.py # ENTRYPOINT 用法 ENTRYPOINT ["python"] CMD ["app.py"] # 固定执行 python,参数可替换 # 实际效果: # docker run myimage → python app.py # docker run myimage test.py → python test.py