1. Dockerfile 是什么?

Dockerfile 是一个文本文件,里面包含了一系列指令,用来定义如何构建一个 Docker 镜像。你可以把它想象成一个“菜谱”,Docker 会根据这个“菜谱”一步步构建出你想要的镜像。


2. Dockerfile 的基本结构

一个典型的 Dockerfile 由多个指令组成,每个指令对应一个操作。以下是一个简单的 Dockerfile 示例:

Dockerfile复制代码

# 基础镜像
FROM ubuntu:20.04

# 设置工作目录
WORKDIR /app

# 复制文件到容器中
COPY . .

# 安装依赖
RUN apt-get update && apt-get install -y python3

# 暴露端口
EXPOSE 80

# 运行命令
CMD ["python3", "app.py"]

3. Dockerfile 常用指令详解

1. FROM

  • 作用:指定基础镜像。
  • 语法FROM <镜像名>:<标签>
  • 示例FROM ubuntu:20.04
    • 这里我们使用 ubuntu:20.04 作为基础镜像。

2. WORKDIR

  • 作用:设置工作目录。后续的命令(如 RUNCOPY 等)都会在这个目录下执行。
  • 语法WORKDIR <路径>
  • 示例WORKDIR /app
    • 这里我们将工作目录设置为 /app

3. COPY

  • 作用:将本地文件或目录复制到容器中。
  • 语法COPY <源路径> <目标路径>
  • 示例COPY . .
    • 这里我们将当前目录下的所有文件复制到容器的 /app 目录下。

4. RUN

  • 作用:在构建镜像时执行命令。通常用于安装软件包或配置环境。
  • 语法RUN <命令>
  • 示例RUN apt-get update && apt-get install -y python3
    • 这里我们更新包管理器并安装 python3

5. EXPOSE

  • 作用:声明容器运行时监听的端口。注意,这只是一个声明,并不会自动映射到主机端口。
  • 语法EXPOSE <端口号>
  • 示例EXPOSE 80
    • 这里我们声明容器会监听 80 端口。

6. CMD

  • 作用:指定容器启动时默认执行的命令。一个 Dockerfile 中只能有一个 CMD 指令。
  • 语法CMD ["可执行文件", "参数1", "参数2"]
  • 示例CMD ["python3", "app.py"]
    • 这里我们指定容器启动时运行 python3 app.py

7. ENV

  • 作用:设置环境变量。
  • 语法ENV <变量名>=<值>
  • 示例ENV PYTHON_VERSION=3.8
    • 这里我们设置了一个环境变量 PYTHON_VERSION

8. ADD

  • 作用:类似于 COPY,但功能更强大。除了复制文件,还可以解压 tar 文件或从 URL 下载文件。
  • 语法ADD <源路径> <目标路径>
  • 示例ADD https://example.com/file.tar.gz /app
    • 这里我们从 URL 下载文件并解压到 /app 目录。

9. ENTRYPOINT

  • 作用:指定容器启动时执行的命令。与 CMD 类似,但 ENTRYPOINT 的参数不会被覆盖。
  • 语法ENTRYPOINT ["可执行文件", "参数1", "参数2"]
  • 示例ENTRYPOINT ["python3"] CMD ["app.py"]
    • 这里我们指定容器启动时运行 python3,默认参数是 app.py

10. VOLUME

  • 作用:声明一个挂载点,用于持久化数据。
  • 语法VOLUME <路径>
  • 示例VOLUME /data
    • 这里我们声明了一个挂载点 /data

4. Dockerfile 最佳实践

1. 减少镜像层数

  • 每个 RUNCOPYADD 等指令都会创建一个新的镜像层。为了减少镜像大小,可以将多个命令合并到一个 RUN 中。Dockerfile复制代码RUN apt-get update && apt-get install -y python3 && apt-get clean

2. 使用 .dockerignore

  • 类似于 .gitignore.dockerignore 可以排除不需要的文件,避免它们被复制到镜像中。

3. 多阶段构建

  • 如果你的构建过程比较复杂,可以使用多阶段构建来减少最终镜像的大小。Dockerfile复制代码FROM node:14 AS build WORKDIR /app COPY . . RUN npm install && npm run build FROM nginx:alpine COPY --from=build /app/dist /usr/share/nginx/html

5. 实战:编写一个 Python 应用的 Dockerfile

假设你有一个 Python 应用,目录结构如下:

my-app/
├── app.py
├── requirements.txt
└── Dockerfile

Dockerfile 内容

# 使用官方的 Python 镜像作为基础镜像
FROM python:3.8-slim

# 设置工作目录
WORKDIR /app

# 复制依赖文件
COPY requirements.txt .

# 安装依赖
RUN pip install --no-cache-dir -r requirements.txt

# 复制应用代码
COPY . .

# 暴露端口
EXPOSE 5000

# 运行应用
CMD ["python", "app.py"]

构建镜像

docker build -t my-python-app .

运行容器

docker run -p 5000:5000 my-python-app

基础镜像

1. 操作系统基础镜像

这些镜像提供了最基本的操作系统环境,适合需要完全自定义的场景。

1.1 Ubuntu

  • 镜像名ubuntu
  • 特点:功能全面,适合大多数 Linux 应用。
  • 常用标签
    • ubuntu:20.04(LTS 版本)
    • ubuntu:22.04(最新 LTS 版本)
    • ubuntu:latest(最新稳定版)

1.2 Alpine

  • 镜像名alpine
  • 特点:非常轻量(只有 5MB 左右),适合对镜像大小敏感的场景。
  • 常用标签
    • alpine:3.14
    • alpine:latest

1.3 CentOS

  • 镜像名centos
  • 特点:稳定且广泛用于企业环境。
  • 常用标签
    • centos:7
    • centos:8
    • centos:latest

1.4 Debian

  • 镜像名debian
  • 特点:稳定且轻量,适合需要精简环境的场景。
  • 常用标签
    • debian:buster
    • debian:bullseye
    • debian:latest

2. 语言运行时基础镜像

这些镜像已经预装了特定语言的运行时环境,适合直接运行应用程序。

Python

  • 官方镜像:python:3.11-alpine(轻量版)或 python:3.11-slim(Debian 精简版)。
  • 特点:提供不同版本和变体,支持直接运行 Python 应用。

Node.js

  • 官方镜像:node:18-alpine 或 node:18-bullseye-slim
  • 特点:含 npm/yarn,适合前端或 Node 后端服务。

Golang

  • 官方镜像:golang:1.20-alpine(编译环境),部署时通常使用多阶段构建复制二进制文件到 scratch 或 alpine

Java

  • 官方镜像:eclipse-temurin:17-jdk-jammy(OpenJDK,基于 Ubuntu)或 eclipse-temurin:17-jdk-alpine(轻量版)。

PHP

  • 官方镜像:php:8.2-apache(含 Apache)或 php:8.2-fpm(与 Nginx 配合)。

3. 数据库基础镜像

这些镜像预装了数据库服务,适合快速部署数据库。

3.1 MySQL

  • 镜像名mysql
  • 特点:预装了 MySQL 数据库。
  • 常用标签
    • mysql:5.7
    • mysql:8.0
    • mysql:latest

3.2 PostgreSQL

  • 镜像名postgres
  • 特点:预装了 PostgreSQL 数据库。
  • 常用标签
    • postgres:13
    • postgres:latest

3.3 Redis

  • 镜像名redis
  • 特点:预装了 Redis 缓存服务。
  • 常用标签
    • redis:6.2
    • redis:latest

4. Web 服务器基础镜像

这些镜像预装了 Web 服务器,适合快速部署 Web 应用。

4.1 Nginx

  • 镜像名nginx
  • 特点:预装了 Nginx Web 服务器。
  • 常用标签
    • nginx:1.21
    • nginx:latest

4.2 Apache HTTP Server

  • 镜像名httpd
  • 特点:预装了 Apache HTTP 服务器。
  • 常用标签
    • httpd:2.4
    • httpd:latest

5. 特殊用途基础镜像

这些镜像针对特定场景进行了优化。

5.1 Scratch

  • 镜像名scratch
  • 特点:空镜像,适合构建完全静态的二进制文件。
  • 示例FROM scratch COPY my-app / CMD ["/my-app"]

5.2 BusyBox

  • 镜像名busybox
  • 特点:非常轻量,适合嵌入式或资源受限的环境。
  • 常用标签
    • busybox:latest

5.2 Distroless(Google 维护)

  • 镜像名gcr.io/distroless/basegcr.io/distroless/nodejs18
  • 特点:仅包含应用和运行时,无 Shell、包管理器,提升安全性。
  • 适用场景:生产环境,减少攻击面。

    6. 如何选择基础镜像?

    • 镜像大小:如果对镜像大小敏感,可以选择 alpine 或 slim 版本。
    • 安全性:选择官方维护的镜像,并定期更新。
    • 功能需求:如果需要特定语言或工具,选择对应的运行时镜像。

    7. 示例:使用 Alpine 作为基础镜像

    以下是一个使用 alpine 作为基础镜像的 Dockerfile 示例:

    # 使用 Alpine 作为基础镜像
    FROM alpine:3.14
    
    # 安装 Python 和 pip
    RUN apk add --no-cache python3 py3-pip
    
    # 设置工作目录
    WORKDIR /app
    
    # 复制应用代码
    COPY . .
    
    # 安装依赖
    RUN pip3 install -r requirements.txt
    
    # 暴露端口
    EXPOSE 5000
    
    # 运行应用
    CMD ["python3", "app.py"]


    一沙一世界,一花一天堂。君掌盛无边,刹那成永恒。