[CI/CD] - 容器技术 - Docker & Docker Compose
Docker 详细介绍
Docker 是什么?
Docker 是一个开源的容器化平台,用于开发、部署和运行应用程序。它将应用程序及其依赖项打包到一个标准化的单元(容器)中,确保在任何环境中都能一致运行。
Docker 的核心概念
1. 容器(Container)
-
轻量级、可执行的软件包
-
包含运行应用程序所需的一切
-
与宿主机和其他容器隔离
2. 镜像(Image)
-
容器的只读模板
-
包含应用程序代码、运行时、库、环境变量和配置文件
-
多层结构,便于复用和增量更新
3. 仓库(Registry)
-
存储和分发 Docker 镜像的地方
-
公共仓库:Docker Hub
-
私有仓库:企业自建
4. Dockerfile
-
用于构建 Docker 镜像的文本文件
-
包含一系列指令
Docker 的优势
1. 环境一致性
-
"一次构建,到处运行"
-
消除"在我机器上能运行"的问题
2. 快速部署
-
秒级启动和停止
-
轻量级,资源占用少
3. 隔离性
-
进程级别的隔离
-
资源限制和控制
4. 版本控制和组件重用
-
镜像版本管理
-
基础镜像复用
5. 微服务友好
-
每个服务独立容器化
-
便于扩展和更新
Docker 安装
1. Linux 安装
bash
# Ubuntu/Debian sudo apt update sudo apt install -y apt-transport-https ca-certificates curl software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin # 验证安装 sudo docker --version # 将当前用户添加到 docker 组(避免每次使用 sudo) sudo usermod -aG docker $USER # 重新登录或执行以下命令 newgrp docker
2. macOS 安装
bash
# 使用 Homebrew brew install --cask docker # 或从 Docker 官网下载 Docker Desktop # https://www.docker.com/products/docker-desktop/
3. Windows 安装
bash
# 从 Docker 官网下载 Docker Desktop # 需要 Windows 10/11 Pro 或 Enterprise 版本 # 或使用 WSL2
Docker 基础命令
1. 镜像管理
bash
# 搜索镜像 docker search nginx docker search ubuntu --filter "is-official=true" # 拉取镜像 docker pull ubuntu:20.04 docker pull nginx:latest docker pull python:3.9-slim # 列出本地镜像 docker images docker image ls docker images -a # 显示所有镜像(包括中间层) # 删除镜像 docker rmi ubuntu:20.04 docker image rm nginx:latest docker image prune # 删除未使用的镜像 docker image prune -a # 删除所有未使用的镜像 # 镜像标签 docker tag ubuntu:20.04 my-ubuntu:v1 # 查看镜像详情 docker image inspect ubuntu:20.04 # 保存镜像到文件 docker save -o ubuntu.tar ubuntu:20.04 # 从文件加载镜像 docker load -i ubuntu.tar
2. 容器管理
bash
# 运行容器
docker run ubuntu:20.04 echo "Hello Docker"
docker run -it ubuntu:20.04 /bin/bash # 交互式运行
docker run -d -p 80:80 --name my-nginx nginx # 后台运行
docker run -d --name myapp -v $(pwd):/app -w /app python:3.9 python app.py
# 常用运行选项
docker run \
-d \ # 后台运行
--name mycontainer \ # 容器名称
-p 8080:80 \ # 端口映射 主机:容器
-v /host/path:/container/path \ # 卷挂载
-e ENV_VAR=value \ # 环境变量
--network mynetwork \ # 网络
--restart=always \ # 重启策略
--memory="512m" \ # 内存限制
--cpus="1.5" \ # CPU限制
image:tag
# 列出容器
docker ps # 运行中的容器
docker ps -a # 所有容器
docker ps -q # 只显示容器ID
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
# 启动/停止/重启容器
docker start mycontainer
docker stop mycontainer
docker restart mycontainer
docker pause mycontainer
docker unpause mycontainer
# 进入容器
docker exec -it mycontainer /bin/bash
docker exec mycontainer ls /app
# 查看容器日志
docker logs mycontainer
docker logs -f mycontainer # 实时查看
docker logs --tail 100 mycontainer
docker logs --since 10m mycontainer
# 查看容器进程
docker top mycontainer
# 查看容器详情
docker inspect mycontainer
# 容器与主机文件复制
docker cp mycontainer:/app/config.json ./config.json
docker cp ./data.txt mycontainer:/tmp/data.txt
# 删除容器
docker rm mycontainer
docker rm -f mycontainer # 强制删除运行中的容器
docker container prune # 删除所有停止的容器
3. 容器状态管理
bash
# 查看容器资源使用
docker stats
docker stats mycontainer
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
# 查看容器端口映射
docker port mycontainer
# 重命名容器
docker rename old_name new_name
# 更新容器配置
docker update --restart=always mycontainer
docker update --memory=1g mycontainer
Dockerfile 详解
1. 基本结构
dockerfile
# 基础镜像
FROM ubuntu:20.04
# 维护者信息(可选)
LABEL maintainer="your.email@example.com"
LABEL version="1.0"
LABEL description="My application"
# 设置环境变量
ENV DEBIAN_FRONTEND=noninteractive
ENV APP_HOME=/app
ENV PYTHONUNBUFFERED=1
# 设置工作目录
WORKDIR $APP_HOME
# 复制文件
COPY requirements.txt .
COPY src/ ./src/
COPY --from=stage0 /build/output /app # 多阶段构建
# 添加文件(支持URL和解压)
ADD https://example.com/data.tar.gz /tmp/
ADD app.tar.gz /app/
# 运行命令
RUN apt update && apt install -y \
python3 \
python3-pip \
&& pip3 install --no-cache-dir -r requirements.txt \
&& apt clean \
&& rm -rf /var/lib/apt/lists/*
# 暴露端口
EXPOSE 8080
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/health || exit 1
# 用户切换
USER appuser
# 入口点
ENTRYPOINT ["python3"]
# 命令参数
CMD ["app.py"]
2. 最佳实践示例
dockerfile
# 多阶段构建示例 # 第一阶段:构建环境 FROM python:3.9-slim AS builder WORKDIR /app COPY requirements.txt . RUN pip install --user -r requirements.txt # 第二阶段:运行环境 FROM python:3.9-slim # 创建非root用户 RUN groupadd -r appgroup && useradd -r -g appgroup appuser WORKDIR /app # 从构建阶段复制已安装的包 COPY --from=builder /root/.local /home/appuser/.local COPY --chown=appuser:appgroup . . # 设置用户 USER appuser # 添加到PATH ENV PATH=/home/appuser/.local/bin:$PATH # 健康检查 HEALTHCHECK --interval=30s --timeout=5s --start-period=10s \ CMD python healthcheck.py EXPOSE 8080 CMD ["python", "app.py"]
3. 构建镜像
bash
# 构建镜像 docker build -t myapp:latest . docker build -t myapp:v1.0 -f Dockerfile.prod . # 构建参数 docker build \ --build-arg VERSION=1.0 \ --no-cache \ # 不使用缓存 --progress=plain \ # 详细输出 -t myapp:latest . # 查看构建历史 docker history myapp:latest
Docker Compose
1. docker-compose.yml 示例
yaml
version: '3.8'
services:
web:
image: nginx:alpine
container_name: my-nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./html:/usr/share/nginx/html
- ./logs:/var/log/nginx
environment:
- NGINX_HOST=localhost
- NGINX_PORT=80
env_file:
- .env
networks:
- frontend
depends_on:
- app
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
app:
build:
context: .
dockerfile: Dockerfile
args:
VERSION: 1.0
image: myapp:latest
container_name: my-app
ports:
- "8080:8080"
volumes:
- ./app:/app
- app-data:/data
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
- REDIS_URL=redis://redis:6379/0
networks:
- frontend
- backend
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
command: ["python", "app.py"]
deploy:
resources:
limits:
cpus: '0.50'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
db:
image: postgres:13-alpine
container_name: postgres-db
environment:
POSTGRES_DB: mydb
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_INITDB_ARGS: "--encoding=UTF8 --lc-collate=C --lc-ctype=C"
volumes:
- postgres-data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- backend
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:6-alpine
container_name: redis-cache
command: redis-server --appendonly yes
volumes:
- redis-data:/data
networks:
- backend
ports:
- "6379:6379"
phpmyadmin:
image: phpmyadmin/phpmyadmin
container_name: phpmyadmin
environment:
PMA_HOST: db
PMA_PORT: 5432
ports:
- "8081:80"
networks:
- backend
depends_on:
- db
networks:
frontend:
driver: bridge
backend:
driver: bridge
volumes:
postgres-data:
driver: local
redis-data:
driver: local
app-data:
2. Docker Compose 命令
bash
# 启动服务 docker-compose up docker-compose up -d # 后台运行 docker-compose up --build # 重新构建并启动 docker-compose up web db # 启动指定服务 # 停止服务 docker-compose down docker-compose down -v # 同时删除卷 docker-compose down --rmi all # 同时删除镜像 # 查看状态 docker-compose ps docker-compose top docker-compose logs docker-compose logs -f web # 实时查看指定服务日志 # 服务管理 docker-compose start docker-compose stop docker-compose restart docker-compose pause docker-compose unpause # 执行命令 docker-compose exec web bash docker-compose exec db psql -U user -d mydb # 构建 docker-compose build docker-compose build --no-cache # 其他 docker-compose config # 验证配置 docker-compose pull # 拉取镜像 docker-compose images # 查看镜像 docker-compose port web 80 # 查看端口映射
Docker 网络
1. 网络类型
bash
# 查看网络 docker network ls # 创建网络 docker network create my-network docker network create --driver bridge --subnet 172.20.0.0/16 --gateway 172.20.0.1 my-network # 容器连接网络 docker run --network my-network --name container1 nginx docker network connect my-network existing-container docker network disconnect my-network container1 # 查看网络详情 docker network inspect my-network # 删除网络 docker network rm my-network docker network prune # 删除未使用的网络
2. 网络模式
bash
# bridge (默认) docker run --network bridge nginx # host (使用主机网络) docker run --network host nginx # none (无网络) docker run --network none nginx # container (共享其他容器网络) docker run --network container:other-container nginx # 自定义网络 (推荐) docker network create app-network docker run --network app-network --name service1 nginx docker run --network app-network --name service2 nginx # service1 和 service2 可以通过容器名互相访问
Docker 存储
1. 数据卷(Volumes)
bash
# 创建卷 docker volume create my-volume # 列出卷 docker volume ls # 使用卷 docker run -v my-volume:/data nginx docker run --mount source=my-volume,target=/data nginx # 查看卷详情 docker volume inspect my-volume # 删除卷 docker volume rm my-volume docker volume prune # 删除未使用的卷
2. 绑定挂载(Bind Mounts)
bash
# 挂载主机目录 docker run -v /host/path:/container/path nginx docker run --mount type=bind,source=/host/path,target=/container/path nginx # 只读挂载 docker run -v /host/path:/container/path:ro nginx
3. 临时文件系统(tmpfs)
bash
# 内存中的临时文件系统 docker run --tmpfs /app/temp nginx docker run --mount type=tmpfs,target=/app/temp nginx
Docker 多阶段构建
1. 示例:Go 应用
dockerfile
# 第一阶段:构建 FROM golang:1.18 AS builder WORKDIR /app COPY . . # 编译 RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main . # 第二阶段:运行 FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /root/ # 从构建阶段复制二进制文件 COPY --from=builder /app/main . # 运行 CMD ["./main"]
2. 示例:Node.js 应用
dockerfile
# 第一阶段:依赖安装 FROM node:16 AS deps WORKDIR /app COPY package*.json ./ RUN npm ci --only=production # 第二阶段:构建 FROM node:16 AS builder WORKDIR /app COPY . . COPY --from=deps /app/node_modules ./node_modules RUN npm run build # 第三阶段:运行 FROM node:16-alpine WORKDIR /app ENV NODE_ENV=production USER node COPY --from=builder /app/dist ./dist COPY --from=deps /app/node_modules ./node_modules COPY package.json . EXPOSE 3000 CMD ["node", "dist/index.js"]
Docker 安全最佳实践
1. 最小化镜像
dockerfile
# 使用官方精简镜像
FROM python:3.9-slim
# 合并 RUN 命令,减少层数
RUN apt update && apt install -y \
build-essential \
&& rm -rf /var/lib/apt/lists/*
2. 非 root 用户运行
dockerfile
# 创建用户和组 RUN groupadd -r appgroup && useradd -r -g appgroup appuser # 设置用户 USER appuser
3. 扫描镜像漏洞
bash
# 使用 Docker Scout docker scout cve myapp:latest # 使用 Trivy docker run --rm aquasec/trivy image myapp:latest
4. 安全配置
bash
# 限制容器资源 docker run --memory="512m" --cpus="1.0" nginx # 只读根文件系统 docker run --read-only nginx # 安全选项 docker run --security-opt="no-new-privileges" nginx docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx
实际应用示例
1. 开发环境
yaml
# docker-compose.dev.yml
version: '3.8'
services:
web:
build: .
volumes:
- .:/app
- /app/node_modules # 防止覆盖容器内的 node_modules
ports:
- "3000:3000"
environment:
- NODE_ENV=development
command: npm run dev
db:
image: postgres:13
environment:
POSTGRES_PASSWORD: devpass
volumes:
- postgres-data:/var/lib/postgresql/data
redis:
image: redis:6-alpine
ports:
- "6379:6379"
volumes:
postgres-data:
2. 生产环境
yaml
# docker-compose.prod.yml
version: '3.8'
services:
web:
image: myregistry/myapp:${TAG:-latest}
restart: always
ports:
- "80:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://user:${DB_PASSWORD}@db:5432/mydb
depends_on:
- db
networks:
- app-network
deploy:
resources:
limits:
memory: 512M
db:
image: postgres:13-alpine
restart: always
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: mydb
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- app-network
networks:
app-network:
volumes:
postgres-data:
3. CI/CD 集成
yaml
# .gitlab-ci.yml 示例
stages:
- build
- test
- deploy
variables:
DOCKER_TLS_CERTDIR: ""
build:
stage: build
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
test:
stage: test
script:
- docker run --rm $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA npm test
deploy:
stage: deploy
script:
- docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest
- docker push $CI_REGISTRY_IMAGE:latest
- ssh deploy@server "cd /app && docker-compose pull && docker-compose up -d"
Docker 监控和日志
1. 日志管理
bash
# 日志驱动 docker run --log-driver=json-file nginx # 默认 docker run --log-driver=syslog nginx docker run --log-driver=journald nginx docker run --log-driver=gelf nginx # 日志选项 docker run --log-opt max-size=10m --log-opt max-file=3 nginx # 查看日志 docker logs --tail 50 --follow --timestamps mycontainer
2. 监控工具
bash
# 使用 cAdvisor docker run \ --volume=/:/rootfs:ro \ --volume=/var/run:/var/run:ro \ --volume=/sys:/sys:ro \ --volume=/var/lib/docker/:/var/lib/docker:ro \ --publish=8080:8080 \ --detach=true \ --name=cadvisor \ google/cadvisor:latest # 使用 Portainer(Web UI) docker run -d -p 9000:9000 --name portainer \ --restart=always \ -v /var/run/docker.sock:/var/run/docker.sock \ -v portainer_data:/data \ portainer/portainer-ce
常见问题解决
1. Docker 启动失败
bash
# 检查 Docker 服务状态
sudo systemctl status docker
# 查看 Docker 日志
sudo journalctl -u docker
# 常见问题:端口冲突
# 解决方案:修改 Docker 配置文件
sudo vim /etc/docker/daemon.json
{
"hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"]
}
sudo systemctl restart docker
2. 磁盘空间不足
bash
# 清理未使用的资源 docker system prune docker system prune -a # 更彻底 docker volume prune docker image prune # 查看磁盘使用 docker system df # 清理特定资源 docker rm $(docker ps -aq) docker rmi $(docker images -q)
3. 网络连接问题
bash
# 检查网络配置
docker network ls
docker network inspect bridge
# 重启 Docker 网络
sudo systemctl restart docker
# 自定义 DNS
# 在 /etc/docker/daemon.json 中添加
{
"dns": ["8.8.8.8", "8.8.4.4"]
}
4. 权限问题
bash
# 将用户加入 docker 组 sudo usermod -aG docker $USER newgrp docker # 修复 Docker socket 权限 sudo chmod 666 /var/run/docker.sock # 或者使用 sudo(不推荐长期使用) sudo docker ps
Docker 高级特性
1. Docker Swarm(集群管理)
bash
# 初始化 Swarm docker swarm init --advertise-addr <MANAGER-IP> # 加入节点 docker swarm join --token <TOKEN> <MANAGER-IP>:2377 # 部署服务 docker service create --replicas 3 --name web nginx:alpine # 查看服务 docker service ls docker service ps web # 更新服务 docker service update --image nginx:latest web
2. BuildKit(新一代构建工具)
bash
# 启用 BuildKit
export DOCKER_BUILDKIT=1
# 或修改 Docker 配置
# /etc/docker/daemon.json
{
"features": {
"buildkit": true
}
}
# 使用 BuildKit 构建
docker buildx build --platform linux/amd64,linux/arm64 -t myapp:latest .
3. Docker Content Trust(镜像签名)
bash
# 启用镜像签名 export DOCKER_CONTENT_TRUST=1 # 推送签名镜像 docker push myregistry/myapp:latest # 拉取签名镜像 docker pull myregistry/myapp:latest
总结
Docker 已经成为现代软件开发和部署的标准工具,它通过容器化技术解决了环境一致性问题,提高了开发和运维效率。
学习建议:
-
从基础命令开始,掌握镜像和容器的基本操作
-
学习编写 Dockerfile,理解镜像构建过程
-
掌握 Docker Compose,用于多容器应用管理
-
学习 Docker 网络和存储,理解容器间通信和数据持久化
-
实践安全最佳实践,确保生产环境安全
-
探索 Docker 生态,如 Kubernetes、监控工具等
Docker 的学习曲线相对平缓,但深度使用需要理解其背后的原理。建议在实际项目中应用所学知识,逐步掌握高级特性。
帮助文档和学习资源
官方文档
-
Docker 官方文档:https://docs.docker.com/
-
Docker Hub:https://hub.docker.com/
-
Docker 官方教程:https://docs.docker.com/get-started/
-
Dockerfile 参考:https://docs.docker.com/engine/reference/builder/
中文资源
-
Docker 从入门到实践:https://yeasy.gitbook.io/docker_practice/
-
Docker 中文指南:https://dockerchina.github.io/
-
Docker 教程 - 菜鸟教程:https://www.runoob.com/docker/docker-tutorial.html
学习平台
-
Docker 官方实验室:https://labs.play-with-docker.com/
-
Katacoda Docker 课程:https://www.katacoda.com/courses/docker
-
Udemy Docker 课程:https://www.udemy.com/topic/docker/
书籍推荐
-
《Docker 从入门到实践》 - 杨保华
-
《Docker 技术入门与实战》 - 杨保华
-
《Using Docker》 - Adrian Mouat
-
《Docker Deep Dive》 - Nigel Poulton
社区和论坛
-
Docker 官方论坛:https://forums.docker.com/
-
Stack Overflow Docker 标签:https://stackoverflow.com/questions/tagged/docker
-
Reddit r/docker:https://www.reddit.com/r/docker/
-
GitHub Docker 组织:https://github.com/docker
视频教程
-
Docker 官方 YouTube:https://www.youtube.com/user/dockerrun
-
Docker 入门教程 - 狂神说:https://www.bilibili.com/video/BV1og4y1q7M4
-
Docker 完整课程 - freeCodeCamp:https://www.youtube.com/watch?v=3c-iBn73dDE
认证和培训
-
Docker 认证助理(DCA):https://www.docker.com/certification/
-
Docker 官方培训:https://www.docker.com/training/
更多推荐




所有评论(0)