Docker_02_Dockerfile与存储网络

Dockerfile 与存储网络:构建镜像的完整指南

一、Dockerfile 基础

1.1 什么是 Dockerfile?

Dockerfile 是一个文本文件,包含了一系列指令,用于自动构建 Docker 镜像。通过 docker build 命令读取 Dockerfile 中的指令,按顺序执行并生成镜像。

1.2 基本语法

dockerfile 复制代码
# 注释以 # 开头
# 指令格式:INSTRUCTION arguments
# 指令不区分大小写,但约定大写

二、Dockerfile 核心指令

2.1 FROM:指定基础镜像

dockerfile 复制代码
# 格式:FROM <image>[:<tag>] [AS <name>]
FROM ubuntu:22.04
FROM node:18-alpine AS builder
FROM scratch  # 空镜像,从零开始

最佳实践:

  • 使用 Alpine 版本减小镜像体积
  • 使用具体的 tag 而不是 latest
  • 多阶段构建时给阶段命名

2.2 RUN:执行命令

dockerfile 复制代码
# Shell 格式(默认)
RUN echo "Hello World"
RUN apt-get update && apt-get install -y nginx

# Exec 格式
RUN ["echo", "Hello World"]

最佳实践:

  • 多个命令用 && 连接,减少镜像层数
  • 清理缓存:apt-get clean && rm -rf /var/lib/apt/lists/*

2.3 COPY 与 ADD:复制文件

dockerfile 复制代码
# COPY:简单复制本地文件
COPY package.json /app/
COPY . /app/
COPY ["package.json", "/app/"]

# ADD:功能更强,支持自动解压 tar 和远程 URL
ADD app.tar.gz /app/  # 自动解压
ADD https://example.com/file.zip /app/  # 下载远程文件

区别:

  • COPY 只能复制本地文件,语义更明确
  • ADD 可以自动解压 tar 包,支持下载远程文件
  • 推荐优先使用 COPY,需要解压功能时用 ADD

2.4 WORKDIR:设置工作目录

dockerfile 复制代码
WORKDIR /app
COPY package.json .  # 相当于 COPY package.json /app/
RUN npm install      # 在 /app 目录下执行

作用:设置后续指令的工作目录,如果不存在会自动创建。

2.5 EXPOSE:声明端口

dockerfile 复制代码
EXPOSE 80
EXPOSE 8080 8443

注意 :EXPOSE 只是声明,不会自动映射端口。运行容器时仍需用 -p 参数映射。

2.6 ENV:设置环境变量

dockerfile 复制代码
ENV NODE_ENV=production
ENV APP_PORT=3000 APP_NAME=myapp

运行时可以通过 -e 覆盖:docker run -e NODE_ENV=dev myapp

2.7 ARG:构建参数

dockerfile 复制代码
ARG VERSION=1.0
FROM ubuntu:${VERSION}

构建时通过 --build-arg 传入:docker build --build-arg VERSION=2.0 .

区别:ENV 设置的环境变量会保留到容器中,ARG 只在构建时有效。

2.8 CMD:容器启动命令

dockerfile 复制代码
# Shell 格式
CMD echo "Hello World"
CMD nginx -g "daemon off;"

# Exec 格式(推荐)
CMD ["nginx", "-g", "daemon off;"]
CMD ["node", "app.js"]

特点:

  • 一个 Dockerfile 只能有一个 CMD
  • 如果有多个 CMD,只有最后一个生效
  • docker run 后面跟的命令会覆盖 CMD

2.9 ENTRYPOINT:容器入口点

dockerfile 复制代码
# Exec 格式(推荐)
ENTRYPOINT ["nginx", "-g", "daemon off;"]
ENTRYPOINT ["python", "app.py"]

与 CMD 的区别:

  • ENTRYPOINT 不会被 docker run 命令覆盖(除非用 --entrypoint)
  • docker run 后面的参数会作为 ENTRYPOINT 的参数传递
  • CMD 通常作为 ENTRYPOINT 的默认参数
dockerfile 复制代码
ENTRYPOINT ["python"]
CMD ["app.py"]  # 默认参数
bash 复制代码
docker run myapp           # 执行 python app.py
docker run myapp script.py # 执行 python script.py

2.10 其他常用指令

dockerfile 复制代码
# VOLUME:声明匿名卷
VOLUME ["/data", "/logs"]

# USER:指定运行用户
USER nobody

# LABEL:添加元数据标签
LABEL version="1.0" maintainer="dev@example.com"

# HEALTHCHECK:健康检查
HEALTHCHECK --interval=30s --timeout=3s \
    CMD curl -f http://localhost/ || exit 1

# SHELL:更改默认 shell
SHELL ["/bin/bash", "-c"]

三、Dockerfile 实战

3.1 Node.js 应用

dockerfile 复制代码
# 多阶段构建
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

# 最终镜像
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/main.js"]

3.2 Spring Boot 应用

dockerfile 复制代码
FROM eclipse-temurin:21-jdk-alpine AS builder
WORKDIR /app
COPY . .
RUN ./gradlew bootJar --no-daemon

FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=builder /app/build/libs/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

3.3 Python Flask 应用

dockerfile 复制代码
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]

3.4 构建镜像

bash 复制代码
# 基本构建
docker build -t myapp:v1.0 .

# 指定 Dockerfile 路径
docker build -f docker/Dockerfile -t myapp:v1.0 .

# 传递构建参数
docker build --build-arg VERSION=2.0 -t myapp:v2.0 .

# 不使用缓存构建
docker build --no-cache -t myapp:v1.0 .

四、数据持久化

4.1 为什么需要数据持久化?

容器是临时的,删除后数据会丢失。需要持久化:

  • 数据库数据
  • 用户上传的文件
  • 应用日志
  • 配置文件

4.2 数据卷(Volumes)

由 Docker 管理,存储在 Docker 专用目录中。

bash 复制代码
# 创建数据卷
docker volume create mydata

# 查看所有数据卷
docker volume ls

# 查看数据卷详情
docker volume inspect mydata

# 使用数据卷运行容器
docker run -d -v mydata:/var/lib/mysql mysql:8.0

# 删除数据卷
docker volume rm mydata

# 清理所有未使用的数据卷
docker volume prune

特点:

  • 生命周期独立于容器
  • 可以在多个容器间共享
  • 支持备份、迁移
  • 性能优于 Bind Mount

4.3 绑定挂载(Bind Mounts)

将宿主机目录映射到容器。

bash 复制代码
# 挂载宿主机目录
docker run -d -v /home/user/data:/app/data nginx

# 挂载单个文件
docker run -d -v /home/user/config.yml:/app/config.yml nginx

# 只读挂载
docker run -d -v /home/user/data:/app/data:ro nginx

特点:

  • 直接使用宿主机路径
  • 适合开发环境(代码热重载)
  • 依赖宿主机目录结构
  • 性能最好但可移植性差

4.4 选择建议

场景 推荐方式
数据库持久化 Volume
开发环境代码同步 Bind Mount
多个容器共享数据 Volume
配置文件 Bind Mount 或 Config
日志收集 Bind Mount

五、Docker 网络

5.1 网络模式

Docker 提供多种网络模式:

bash 复制代码
# 查看所有网络
docker network ls

# 创建自定义网络
docker network create mynet
docker network create --driver bridge mynet
docker network create --subnet=172.20.0.0/16 mynet

5.2 Bridge 网络(默认)

容器通过虚拟网桥 docker0 通信。

bash 复制代码
# 查看 bridge 网络详情
docker network inspect bridge

# 使用自定义 bridge 网络
docker network create mybridge
docker run -d --network mybridge --name container1 nginx
docker run -d --network mybridge --name container2 nginx

# 容器间通过容器名通信
docker exec container1 ping container2

特点:

  • 默认网络模式
  • 容器有独立 IP
  • 同一网络的容器可以通过容器名互相访问
  • 与宿主机隔离,需要通过端口映射访问

5.3 Host 网络

容器直接使用宿主机网络。

bash 复制代码
docker run -d --network host nginx

特点:

  • 容器不使用独立 IP,直接使用宿主机端口
  • 性能最好(无网络转换)
  • 端口冲突需要自行管理
  • 不适合端口密集的场景

5.4 None 网络

禁用网络功能。

bash 复制代码
docker run -d --network none alpine

特点:

  • 容器没有网络接口
  • 完全隔离
  • 适合纯计算任务

5.5 Overlay 网络(Swarm 模式)

跨主机容器通信。

bash 复制代码
# 初始化 Swarm
docker swarm init

# 创建 overlay 网络
docker network create --driver overlay myoverlay

# 在服务中使用
docker service create --network myoverlay --name myservice nginx

5.6 网络操作命令

bash 复制代码
# 将容器连接到网络
docker network connect mynet mycontainer

# 从网络断开容器
docker network disconnect mynet mycontainer

# 删除网络
docker network rm mynet

# 清理未使用的网络
docker network prune

六、面试高频题

Q1:Dockerfile 中 COPY 和 ADD 有什么区别?

A:COPY 只能复制本地文件,语义明确;ADD 可以自动解压 tar 包,支持下载远程文件。推荐优先使用 COPY,只在需要自动解压时使用 ADD。

Q2:CMD 和 ENTRYPOINT 有什么区别?

A:CMD 设置容器启动的默认命令,可以被 docker run 参数覆盖;ENTRYPOINT 设置容器入口点,不会被覆盖(除非用 --entrypoint),docker run 参数会作为 ENTRYPOINT 的附加参数。通常两者结合使用:ENTRYPOINT 指定可执行程序,CMD 提供默认参数。

Q3:Docker 的 Volume 和 Bind Mount 有什么区别?

A:Volume 由 Docker 管理,存储在 /var/lib/docker/volumes/,生命周期独立于容器,可移植性好;Bind Mount 直接使用宿主机路径,依赖宿主机目录结构,适合开发环境。Volume 推荐用于生产环境,Bind Mount 适合开发测试。

Q4:什么是 Docker 多阶段构建?有什么好处?

A:多阶段构建允许在一个 Dockerfile 中使用多个 FROM 指令,每个阶段可以使用不同的基础镜像。好处是最终镜像只包含运行所需的文件,可以大幅减小镜像体积。例如构建阶段使用完整 JDK,运行阶段只使用 JRE。


下一篇:Docker Compose 多容器编排

相关推荐
ESDWAN1 小时前
外贸企业网络专线选型与落地实战指南
网络·架构
重生之我是小技2 小时前
独享代理IP与共享代理IP的核心区别
网络
涉密IT资质笔记3 小时前
涉密人员脱密期管理规范:期限分级模型、就业限制边界与违规认定标准
java·服务器·前端·网络·数据库
honsor3 小时前
PoE温湿度传感器:一根网线供电+通信,即插即用,机房/配电室/仓库温湿度监测首选
运维·服务器·网络·数据库·人工智能·安全
Ivanqhz4 小时前
干涉图着色
java·服务器·网络·数据库·人工智能·深度学习
xiaoye-duck4 小时前
《Linux 网络编程》深入理解 IO 多路复用:select服务器完善、poll 接口详解与服务端改造实战
linux·网络
guo_wen_qiang4 小时前
云服务器elasticsearch环境搭建-单台
运维·elasticsearch·容器
数字供应链安全产品选型4 小时前
智能体安全选型建议:抛开功能清单,用运行时硬指标甄别真实防护能力
网络·安全
AI备忘录4 小时前
(二十三)华为华三锐捷迈普思科 MLAG 跨设备配置命令(双活网关五厂商对照)
服务器·网络·华为