一、容器技术的前世今生
1.1 从 LXC 到 Docker
容器技术的概念可以追溯到 1979 年 Unix V7 的 chroot 系统调用,它实现了文件系统的隔离。2000 年 FreeBSD 推出了 Jail,将隔离扩展到了进程树、网络和用户权限。2006 年 Google 贡献了 Cgroups(Control Groups),实现了资源限制和审计。2008 年 Linux 内核引入了 Namespaces,提供了进程、网络、挂载点等维度的隔离能力。
LXC(LinuX Containers) 在 2008 年诞生,它是第一个真正意义上完整的 Linux 容器实现,整合了 Cgroups 和 Namespaces。然而 LXC 的操作复杂,缺乏标准化的工具链和镜像管理机制。
2013 年,dotCloud 公司(后更名为 Docker Inc.)开源了 Docker。Docker 在 LXC 的基础上进行了重大创新:
- 分层镜像:Union File System 实现镜像的分层存储,极大提升了存储效率和分发速度
- 标准化格式:统一的镜像格式和分发协议
- 开发工具链:简单易用的命令行工具
- 生态建设:Docker Hub 提供公共镜像仓库
Docker 的出现使得容器技术真正走向了大众开发者,开启了云原生时代的大门。
1.2 Docker 的核心价值
Docker 解决的核心问题:
| 痛点 | 传统方案 | Docker 方案 |
|---|---|---|
| 环境一致性 | 手动配置环境 | 镜像固化环境 |
| 资源利用率 | 每个应用独占 VM | 多容器共享宿主机内核 |
| 部署效率 | 小时级部署 | 秒级启动 |
| 版本管理 | 依赖文档记录 | 镜像版本化追踪 |
| 微服务架构 | 复杂的网络配置 | 原生服务发现机制 |
二、Docker 核心概念
2.1 三大核心组件
Docker 架构由三个核心组件构成:
1. 镜像(Image)
镜像是一个只读的容器模板,包含了运行应用所需的所有内容:代码、运行时、库、环境变量和配置文件。镜像采用分层存储设计,每个镜像由多个只读层叠加而成。
分层存储优势:
| 特性 | 说明 |
|---|---|
| 存储优化 | 相同层只存储一份,节省磁盘空间 |
| 构建加速 | 本地已有的层无需重新下载 |
| 分发高效 | 推送/拉取时只传输差异层 |
| 构建缓存 | Dockerfile 指令未变则复用缓存层 |
2. 容器(Container)
容器是镜像的运行实例。与镜像不同,容器在运行时会添加一个可写层(Container Layer),所有对容器的修改都发生在这一层。容器之间相互隔离,每个容器拥有自己的:
- 进程空间(PID Namespace)
- 网络接口(Network Namespace)
- 文件系统挂载点(Mount Namespace)
- 用户权限(User Namespace)
- IPC 通信(IPC Namespace)
3. 仓库(Registry)
仓库用于存储和分发镜像。Docker Hub 是最大的公共仓库,企业也可以搭建私有仓库(如 Harbor)。
# 仓库地址格式registry.example.com:port/namespace/repository:tag
# 示例docker.io/library/nginx:latest # Docker Hub 官方镜像gcr.io/google-containers/pause:3.1 # Google Container Registryharbor.company.com/prod/web:v2.0 # 私有仓库镜像2.2 Docker 架构图
三、Docker 安装与配置
3.1 主流平台安装方式
Ubuntu/Debian
# 卸载旧版本sudo apt-get remove docker docker-engine docker.io containerd runc
# 安装依赖sudo apt-get updatesudo apt-get install ca-certificates curl gnupg lsb-release
# 添加 Docker 官方 GPG 密钥sudo mkdir -p /etc/apt/keyringscurl -fsSL https://download.docker.com/linux/ubuntu/gpg | \ sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# 添加软件源echo "deb [arch=$(dpkg --print-architecture) \ signed-by=/etc/apt/keyrings/docker.gpg] \ https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装 Docker Enginesudo apt-get updatesudo apt-get install docker-ce docker-ce-cli containerd.io \ docker-buildx-plugin docker-compose-pluginCentOS/RHEL
# 安装必要工具sudo yum install -y yum-utils
# 添加 Docker 仓库sudo yum-config-manager --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
# 安装 Dockersudo yum install -y docker-ce docker-ce-cli containerd.io \ docker-buildx-plugin docker-compose-plugin
# 启动服务sudo systemctl enable --now dockermacOS
推荐使用 OrbStack 替代 Docker Desktop,性能更优:
# 使用 Homebrew 安装brew install orbstack
# 或下载安装包# https://orbstack.dev/OrbStack 相比 Docker Desktop 启动速度快 10 倍,内存占用更低,且完美兼容 Docker CLI。
3.2 Daemon 配置优化
编辑 /etc/docker/daemon.json:
{ "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "3" }, "storage-driver": "overlay2", "registry-mirrors": [ "https://mirror.ccs.tencentyun.com", "https://docker.mirrors.ustc.edu.cn" ], "live-restore": true, "default-ulimits": { "nofile": { "Name": "nofile", "Hard": 65535, "Soft": 65535 } }}配置说明:
| 配置项 | 说明 |
|---|---|
log-opts | 限制日志文件大小,避免磁盘被撑满 |
storage-driver | 存储驱动,overlay2 性能最优 |
registry-mirrors | 镜像加速,国内网络必备 |
live-restore | Daemon 重启时容器保持运行 |
# 重载配置sudo systemctl daemon-reloadsudo systemctl restart docker3.3 非 root 用户使用 Docker
# 将当前用户加入 docker 组sudo usermod -aG docker $USER
# 重新登录或执行newgrp docker
# 验证docker run hello-world四、Docker 镜像管理
4.1 镜像的获取与查看
# 从 Docker Hub 拉取镜像docker pull nginx:1.25-alpine
# 指定平台拉取docker pull --platform linux/arm64 nginx:1.25-alpine
# 查看本地镜像docker images
# 输出示例# REPOSITORY TAG IMAGE ID CREATED SIZE# nginx 1.25-alpine 78b8b9da20c4 2 weeks ago 41.2MB# redis 7-alpine 3e5a4774bfbf 3 weeks ago 32.5MB
# 查看镜像详情docker image inspect nginx:1.25-alpine
# 查看镜像分层历史docker history nginx:1.25-alpine4.2 镜像的导出与导入
# 导出镜像为 tar 文件docker save nginx:1.25-alpine -o nginx.tar
# 压缩导出docker save nginx:1.25-alpine | gzip > nginx.tar.gz
# 导入镜像docker load -i nginx.tar
# 从 tar 文件导入并命名docker load -i nginx.tar && docker tag <IMAGE_ID> my-nginx:v14.3 镜像标签管理
# 创建标签(类似软链接)docker tag nginx:1.25-alpine my-registry/nginx:latestdocker tag nginx:1.25-alpine my-registry/nginx:v1.25
# 推送到私有仓库docker push my-registry/nginx:v1.25
# 删除镜像docker rmi nginx:1.25-alpine
# 强制删除(即使有容器在使用)docker rmi -f nginx:1.25-alpine
# 清理悬空镜像(没有标签的镜像)docker image prune
# 清理所有未使用的镜像docker image prune -a4.4 多架构镜像构建
使用 docker buildx 构建跨平台镜像:
# 创建多架构构建器docker buildx create --name multiarch --use
# 启用 qemu 模拟器(构建非宿主机架构)docker run --privileged --rm tonistiigi/binfmt --install all
# 构建并推送多架构镜像docker buildx build \ --platform linux/amd64,linux/arm64 \ -t my-registry/app:v1.0 \ --push \ .五、Docker 容器操作
5.1 容器的生命周期
5.2 容器创建与运行
# 创建并启动容器(最常用)docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
# 常用参数详解docker run -d \ # 后台运行 --name web-server \ # 指定容器名称 --restart unless-stopped \ # 重启策略 -p 8080:80 \ # 端口映射(宿主机:容器) -v /host/path:/container/path \ # 挂载卷 -e MYSQL_ROOT_PASSWORD=secret \ # 环境变量 --memory="512m" \ # 内存限制 --cpus="1.5" \ # CPU 限制 --network mynet \ # 指定网络 nginx:1.25-alpine
# 交互式运行docker run -it --name my-ubuntu ubuntu:22.04 /bin/bash
# 一次性运行(执行后自动删除)docker run --rm alpine:latest echo "Hello Docker"5.3 重启策略
| 策略 | 行为 |
|---|---|
no | 不自动重启(默认) |
on-failure[:max-retries] | 退出码非 0 时重启,可设置最大重试次数 |
always | 总是重启,除非手动停止 |
unless-stopped | 除非手动停止,否则总是重启 |
# 生产环境推荐docker run -d --restart unless-stopped nginx:latest5.4 容器管理命令
# 查看运行中的容器docker ps
# 查看所有容器(包括已停止)docker ps -a
# 查看容器资源占用docker stats
# 格式化输出docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
# 启动/停止/重启容器docker start web-serverdocker stop web-server # 发送 SIGTERM,优雅关闭docker kill web-server # 发送 SIGKILL,强制关闭docker restart web-server
# 暂停/恢复容器docker pause web-serverdocker unpause web-server
# 查看容器日志docker logs web-serverdocker logs -f --tail 100 web-server # 实时跟踪最近 100 行
# 进入容器执行命令docker exec -it web-server /bin/sh
# 以 root 用户进入(适用于 alpine 等)docker exec -it -u 0 web-server /bin/sh
# 复制文件docker cp ./app.conf web-server:/etc/nginx/docker cp web-server:/var/log/nginx ./logs/
# 查看容器进程docker top web-server
# 查看容器详细信息docker inspect web-server
# 导出容器为镜像docker export web-server | docker import - my-nginx:exported
# 提交容器为镜像(不推荐用于生产)docker commit web-server my-nginx:modified5.5 容器资源限制
# 内存限制docker run -d --memory="512m" nginx # 限制 512MBdocker run -d --memory="1g" --memory-swap="2g" nginx # 内存+交换分区共 2GB
# CPU 限制docker run -d --cpus="1.5" nginx # 1.5 个 CPU 核心docker run -d --cpuset-cpus="0,2" nginx # 绑定到 CPU 0 和 2
# IO 限制docker run -d \ --device-read-bps=/dev/sda:10mb \ # 读速率限制 --device-write-bps=/dev/sda:10mb \ # 写速率限制 nginx
# 综合示例docker run -d \ --name app \ --memory="1g" \ --memory-reservation="512m" \ --cpus="2" \ --cpu-shares=1024 \ --pids-limit=100 \ my-app:latest5.6 容器清理
# 停止所有运行中的容器docker stop $(docker ps -q)
# 删除所有已停止的容器docker container prune
# 删除所有容器(危险操作)docker rm -f $(docker ps -aq)
# 一键清理(容器、网络、悬空镜像、构建缓存)docker system prune
# 深度清理(包括未使用的镜像)docker system prune -a
# 查看磁盘占用docker system df六、Docker 数据卷管理
6.1 三种数据持久化方式
6.2 Volume(推荐方式)
Docker 管理的存储卷,存放在 /var/lib/docker/volumes/ 目录。
# 创建卷docker volume create mydata
# 查看所有卷docker volume ls
# 查看卷详情docker volume inspect mydata
# 使用卷docker run -d \ -v mydata:/app/data \ nginx:latest
# 匿名卷(不指定名称)docker run -d -v /app/data nginx:latest
# 命名卷 + 只读docker run -d \ -v mydata:/app/data:ro \ nginx:latest
# 删除卷docker volume rm mydata
# 清理未使用的卷docker volume prune6.3 Bind Mount(绑定挂载)
将宿主机目录直接映射到容器。
# 绑定挂载docker run -d \ -v /host/www:/usr/share/nginx/html \ nginx:latest
# 使用 $PWD 简化路径docker run -d \ -v $(pwd)/html:/usr/share/nginx/html \ nginx:latest
# 挂载单个文件docker run -d \ -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf:ro \ nginx:latest
# 使用 --mount 语法(更明确)docker run -d \ --mount type=bind,src=$(pwd)/html,dst=/usr/share/nginx/html,readonly \ nginx:latest6.4 tmpfs(临时文件系统)
数据仅存储在内存中,容器停止后数据消失。
# 适用于敏感数据或临时缓存docker run -d \ --tmpfs /tmp:rw,size=100m,mode=1777 \ nginx:latest
# 使用 --mount 语法docker run -d \ --mount type=tmpfs,dst=/tmp,tmpfs-size=104857600 \ nginx:latest6.5 数据卷容器
用于容器间共享数据:
# 创建数据卷容器docker create -v /shared-data --name data-container alpine
# 其他容器引用docker run -d \ --volumes-from data-container \ --name app1 \ nginx
docker run -d \ --volumes-from data-container \ --name app2 \ nginx
# 备份数据卷docker run --rm \ --volumes-from data-container \ -v $(pwd):/backup \ alpine tar czf /backup/data-backup.tar.gz /shared-data
# 恢复数据卷docker run --rm \ --volumes-from data-container \ -v $(pwd):/backup \ alpine tar xzf /backup/data-backup.tar.gz -C /6.6 Volume 对比表
| 特性 | Volume | Bind Mount | tmpfs |
|---|---|---|---|
| 存储位置 | Docker 管理目录 | 宿主机任意位置 | 内存 |
| 可移植性 | 优秀 | 差 | 不适用 |
| 性能 | 良好 | 优秀 | 极佳 |
| 备份迁移 | 简单 | 需自行管理 | 不支持 |
| 多容器共享 | 支持 | 支持 | 不支持 |
| 适用场景 | 生产环境持久化 | 开发环境挂载源码 | 敏感数据/缓存 |
七、Docker 网络配置
7.1 默认网络类型
Docker 安装后自动创建三种网络:
$ docker network lsNETWORK ID NAME DRIVER SCOPEc7b8f5b9a3e0 bridge bridge locald4e8a3b1c2f6 host host localf1b2a3c4d5e7 none null local1. bridge(默认)
每个容器分配独立 IP,通过 NAT 访问外部网络。
# 默认使用 bridge 网络docker run -d --name web nginx
# 查看容器网络信息docker inspect web --format '{{.NetworkSettings.IPAddress}}'2. host
容器共享宿主机网络命名空间,无网络隔离。
# 使用 host 网络docker run -d --network host nginx
# 注意:无需端口映射,直接使用宿主机端口3. none
禁用容器网络。
# 完全禁用网络docker run -d --network none alpine7.2 自定义网络
推荐使用自定义网络实现容器间通信:
自定义网络优势:
| 特性 | 默认 bridge | 自定义 bridge |
|---|---|---|
| 容器间通信 | 需使用 IP 地址 | 可使用容器名(DNS) |
| 网络隔离 | 所有容器同一网络 | 按项目/环境隔离 |
| 动态连接 | 不支持 | 运行时动态连接/断开 |
| IP 地址管理 | 自动分配 | 可指定子网和网关 |
# 创建 bridge 网络docker network create --driver bridge mynet
# 指定子网docker network create \ --driver bridge \ --subnet=172.20.0.0/16 \ --gateway=172.20.0.1 \ mynet
# 容器连接到自定义网络docker run -d --network mynet --name db postgres:15docker run -d --network mynet --name web nginx
# 容器间通过名称通信docker exec web ping db
# 运行时连接网络docker network connect mynet existing-container
# 断开网络docker network disconnect mynet web
# 删除网络docker network rm mynet7.3 端口映射
# 随机端口映射docker run -d -P nginx# -P 自动映射 Dockerfile 中 EXPOSE 的端口
# 指定端口映射docker run -d -p 8080:80 nginx# 格式:宿主机端口:容器端口
# 指定 IP 和端口docker run -d -p 127.0.0.1:8080:80 nginx
# UDP 端口docker run -d -p 53:53/udp dns-server
# 多端口映射docker run -d \ -p 80:80 \ -p 443:443 \ nginx
# 查看端口映射docker port web7.4 网络模式对比
| 模式 | 特点 | 适用场景 |
|---|---|---|
| bridge | 默认模式,NAT 访问外网 | 大多数场景 |
| host | 性能最优,无隔离 | 高性能网络应用 |
| none | 无网络 | 安全隔离场景 |
| 自定义 bridge | 支持 DNS 解析、动态连接 | 微服务架构 |
| overlay | 跨主机通信 | Docker Swarm |
八、Dockerfile 最佳实践
8.1 Dockerfile 基础语法
# 基础镜像FROM node:20-alpine
# 维护者信息LABEL maintainer="team@example.com"
# 设置工作目录WORKDIR /app
# 复制依赖文件(利用缓存层)COPY package*.json ./
# 安装依赖RUN npm ci --only=production
# 复制应用代码COPY . .
# 暴露端口EXPOSE 3000
# 健康检查HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:3000/health || exit 1
# 非 root 用户USER node
# 启动命令CMD ["node", "server.js"]8.2 关键指令详解
| 指令 | 说明 | 最佳实践 |
|---|---|---|
FROM | 基础镜像 | 优先选择 Alpine 或 Distroless |
WORKDIR | 工作目录 | 使用绝对路径 |
COPY | 复制文件 | 分层复制,利用缓存 |
RUN | 执行命令 | 合并多条命令 && |
ENV | 环境变量 | 设置固定值 |
ARG | 构建参数 | 敏感信息传递 |
EXPOSE | 声明端口 | 仅作文档用途 |
CMD | 默认命令 | 使用 JSON 数组格式 |
ENTRYPOINT | 入口点 | 配合 CMD 实现灵活配置 |
HEALTHCHECK | 健康检查 | 生产环境必备 |
8.3 CMD 与 ENTRYPOINT 区别
# CMD 方式:可被 docker run 参数覆盖FROM alpineCMD ["echo", "hello"]# docker run myimage echo world → 输出 world
# ENTRYPOINT 方式:docker run 参数作为追加参数FROM alpineENTRYPOINT ["echo"]CMD ["hello"]# docker run myimage world → 输出 hello world# docker run myimage --help → 输出 echo --help
# 组合使用:ENTRYPOINT 定义命令,CMD 定义默认参数FROM alpineENTRYPOINT ["ping"]CMD ["localhost"]# docker run myimage google.com → ping google.com8.4 多阶段构建
减小镜像体积的核心技术:
多阶段构建前后对比:
# 构建阶段FROM golang:1.21-alpine AS builder
WORKDIR /appCOPY go.* ./RUN go mod download
COPY . .RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /server .
# 运行阶段FROM alpine:3.19
RUN apk --no-cache add ca-certificates tzdata
WORKDIR /appCOPY --from=builder /server .
EXPOSE 8080USER nobody
ENTRYPOINT ["/server"]# 构建镜像docker build -t my-server:v1.0 .
# 镜像大小对比# 单阶段构建:~800MB# 多阶段构建:~15MB8.5 镜像优化技巧
# 不推荐:每一层都增加体积RUN apt-get updateRUN apt-get install -y curlRUN apt-get install -y vimRUN apt-get clean
# 推荐:合并命令,单层完成RUN apt-get update && \ apt-get install -y --no-install-recommends \ curl \ vim && \ apt-get clean && \ rm -rf /var/lib/apt/lists/*
# 不推荐:复制所有文件COPY . /app
# 推荐:配合 .dockerignore# .dockerignore 文件内容:# node_modules# .git# *.log# DockerfileCOPY . /app
# 使用 Alpine 或 Distroless 基础镜像FROM node:20-alpine # ~50MBFROM gcr.io/distroless/nodejs20 # ~20MB,无 shell8.6 安全加固实践
FROM node:20-alpine
# 创建非 root 用户RUN addgroup -g 1000 -S appgroup && \ adduser -u 1000 -S appuser -G appgroup
WORKDIR /app
# 设置文件权限COPY --chown=appuser:appgroup . .
# 只读文件系统# docker run --read-only --tmpfs /tmp ...
# 禁用特权# docker run --cap-drop ALL --cap-add CHOWN ...
USER appuser
# 扫描漏洞# docker scout cves myimage:v1九、Docker Compose 服务编排
9.1 docker-compose.yml 基础
version: "3.8"
services: web: image: nginx:1.25-alpine container_name: web-server restart: unless-stopped ports: - "80:80" - "443:443" volumes: - ./html:/usr/share/nginx/html:ro - ./nginx.conf:/etc/nginx/nginx.conf:ro environment: - TZ=Asia/Shanghai networks: - frontend depends_on: - app
app: build: context: ./app dockerfile: Dockerfile args: NODE_ENV: production restart: unless-stopped environment: - DATABASE_URL=postgres://user:pass@db:5432/mydb - REDIS_URL=redis://cache:6379 networks: - frontend - backend depends_on: db: condition: service_healthy cache: condition: service_started
db: image: postgres:15-alpine restart: unless-stopped environment: POSTGRES_USER: user POSTGRES_PASSWORD: pass POSTGRES_DB: mydb volumes: - postgres-data:/var/lib/postgresql/data networks: - backend healthcheck: test: ["CMD-SHELL", "pg_isready -U user -d mydb"] interval: 10s timeout: 5s retries: 5
cache: image: redis:7-alpine restart: unless-stopped volumes: - redis-data:/data networks: - backend
networks: frontend: backend:
volumes: postgres-data: redis-data:9.2 常用命令
# 启动服务docker compose up -d
# 查看服务状态docker compose ps
# 查看日志docker compose logs -f web
# 进入容器docker compose exec app /bin/sh
# 重新构建并启动docker compose up -d --build
# 停止并删除服务docker compose down
# 删除服务和数据卷docker compose down -v
# 扩容服务docker compose up -d --scale app=3
# 查看配置docker compose config
# 只启动特定服务docker compose up -d db cache9.3 环境变量管理
services: app: image: my-app:latest env_file: - .env - .env.local environment: - NODE_ENV=production - DATABASE_URL=${DB_URL}# .env 文件DB_URL=postgres://user:pass@db:5432/mydbREDIS_URL=redis://cache:6379# 命令行覆盖DB_URL=postgres://prod:pass@prod-db:5432/mydb docker compose up -d9.4 多环境配置
# 项目结构├── docker-compose.yml # 基础配置├── docker-compose.override.yml # 开发环境(自动加载)├── docker-compose.prod.yml # 生产环境└── docker-compose.staging.yml # 预发布环境# 开发环境(自动合并 docker-compose.yml 和 override)docker compose up -d
# 生产环境docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# 使用 --profile 启动可选服务docker compose --profile debug up -dservices: app: image: registry.example.com/app:${VERSION:-latest} deploy: replicas: 3 resources: limits: cpus: "1" memory: 512M reservations: memory: 256M healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 10s retries: 3十、实战案例
10.1 案例 1:Web 应用完整部署
项目结构
my-webapp/├── app/│ ├── src/│ ├── package.json│ └── Dockerfile├── nginx/│ ├── nginx.conf│ └── Dockerfile├── docker-compose.yml└── .envapp/Dockerfile
FROM node:20-alpine AS builderWORKDIR /appCOPY package*.json ./RUN npm ciCOPY . .RUN npm run build
FROM nginx:1.25-alpineCOPY --from=builder /app/dist /usr/share/nginx/htmlCOPY nginx/nginx.conf /etc/nginx/nginx.confEXPOSE 80CMD ["nginx", "-g", "daemon off;"]docker-compose.yml
version: "3.8"
services: web: build: context: . dockerfile: app/Dockerfile ports: - "80:80" restart: unless-stopped10.2 案例 2:CI/CD 流水线集成
GitLab CI 示例
stages: - build - test - deploy
variables: IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
build: stage: build image: docker:24 services: - docker:24-dind script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - docker build -t $IMAGE_TAG . - docker push $IMAGE_TAG
test: stage: test image: $IMAGE_TAG script: - npm test
deploy: stage: deploy image: docker:24 script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - docker pull $IMAGE_TAG - docker tag $IMAGE_TAG $CI_REGISTRY_IMAGE:latest - docker push $CI_REGISTRY_IMAGE:latest only: - main10.3 案例 3:本地开发环境
version: "3.8"
services: app: build: context: . target: development # 使用 Dockerfile 中的开发阶段 volumes: - .:/app - /app/node_modules ports: - "3000:3000" environment: - NODE_ENV=development - CHOKIDAR_USEPOLLING=true command: npm run dev
db: image: postgres:15-alpine ports: - "5432:5432" environment: POSTGRES_USER: dev POSTGRES_PASSWORD: dev POSTGRES_DB: myapp volumes: - dev-db:/var/lib/postgresql/data
redis: image: redis:7-alpine ports: - "6379:6379"
mailhog: image: mailhog/mailhog ports: - "1025:1025" # SMTP - "8025:8025" # Web UI
volumes: dev-db:十一、常见问题排查
11.1 容器无法启动
# 查看容器退出原因docker logs <container_id>docker inspect <container_id> --format '{{.State.ExitCode}}'docker inspect <container_id> --format '{{.State.Error}}'
# 常见错误码# 0 - 正常退出# 1 - 应用错误# 137 - 被 SIGKILL 杀死(OOM)# 139 - 段错误# 143 - 被 SIGTERM 终止11.2 网络连接问题
# 进入容器网络命名空间docker exec -it <container_id> sh
# 测试 DNS 解析nslookup google.com
# 测试网络连通性ping -c 3 8.8.8.8curl -v https://google.com
# 查看 NAT 规则iptables -t nat -L -n
# 重建 Docker 网络docker network prune11.3 磁盘空间不足
# 查看磁盘占用docker system df -v
# 清理策略docker system prune -a --volumes # 清理所有未使用资源
# 迁移 Docker 数据目录# 1. 停止 Dockersudo systemctl stop docker
# 2. 修改 /etc/docker/daemon.json{ "data-root": "/mnt/docker-data"}
# 3. 迁移数据sudo rsync -aP /var/lib/docker/ /mnt/docker-data/
# 4. 启动 Dockersudo systemctl start docker11.4 权限问题
# 容器内访问宿主机文件权限错误# 方案 1:使用用户命名空间映射docker run --user $(id -u):$(id -g) ...
# 方案 2:设置正确的文件权限sudo chown -R 1000:1000 ./data
# 方案 3:在 Dockerfile 中创建匹配用户ARG USER_ID=1000RUN useradd -u $USER_ID -m appuserUSER appuser十二、参考资料
本文基于 Docker 26.x 版本编写,部分命令在不同版本间可能存在差异。建议定期关注 Docker 官方更新日志以获取最新特性。
参考
支持与分享
如果这篇文章对你有帮助,欢迎支持作者或分享给更多人
部分信息可能已经过时






