一、Docker 概述
Docker 是一个开源的应用容器引擎,让开发者可以将应用及其依赖打包到一个轻量级、可移植的容器中,然后发布到任何 Linux 或 Windows 机器上。
容器 vs 虚拟机
| 特性 |
容器 |
虚拟机 |
| 启动速度 |
秒级 |
分钟级 |
| 资源占用 |
MB 级 |
GB 级 |
| 隔离级别 |
进程级 |
系统级 |
| 镜像大小 |
小(共享内核) |
大(完整 OS) |
| 运行密度 |
数百个容器 |
数十个 VM |
核心概念
1 2 3 4
| 镜像(Image) → 类模板,只读的文件系统叠加层 容器(Container) → 镜像的运行实例 仓库(Registry) → 存储和分发镜像的服务(如 Docker Hub) Dockerfile → 构建镜像的脚本
|
二、安装与配置
Ubuntu 安装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| sudo apt remove docker docker-engine docker.io containerd runc
sudo apt update sudo apt install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings curl -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
sudo apt update sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo usermod -aG docker $USER
|
镜像加速
1 2 3 4 5 6 7
| { "registry-mirrors": [ "https://mirror.ccs.tencentyun.com", "https://registry.docker-cn.com" ] }
|
1 2
| sudo systemctl daemon-reload sudo systemctl restart docker
|
三、镜像操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| docker search nginx
docker pull nginx:1.24 docker pull mysql:8.0
docker images
docker rmi nginx:1.24
docker image prune -a
docker save -o nginx.tar nginx:1.24 docker load -i nginx.tar
docker build -t my-app:1.0 . docker build -t my-app:1.0 -f Dockerfile.prod .
|
四、容器操作
基础命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| docker run -d --name my-nginx -p 80:80 nginx:1.24
docker ps
docker ps -a
docker exec -it my-nginx /bin/bash docker exec -it my-nginx sh
docker logs my-nginx docker logs -f my-nginx docker logs --tail 100 my-nginx
docker stop my-nginx docker start my-nginx docker restart my-nginx
docker rm my-nginx docker rm -f my-nginx
docker container prune
|
数据卷
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| docker volume create my-data
docker volume ls
docker run -d -v my-data:/var/lib/mysql mysql:8.0
docker run -d -v /host/path:/container/path nginx:1.24
docker run -d -v /host/config:/config:ro nginx:1.24
docker volume rm my-data docker volume prune
|
网络
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| docker network create my-net
docker network ls
docker run -d --name app --network my-net my-app:1.0
docker run -d --name db --network my-net mysql:8.0 docker run -d --name app --network my-net my-app:1.0
docker network rm my-net
|
五、Dockerfile 编写
基本语法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| FROM eclipse-temurin:17-jre-alpine
LABEL maintainer="dev@example.com"
WORKDIR /app
COPY target/app.jar app.jar
ENV JAVA_OPTS="-Xms512m -Xmx1024m"
EXPOSE 8080
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
|
常用指令
| 指令 |
说明 |
FROM |
基础镜像 |
WORKDIR |
工作目录 |
COPY |
复制文件到镜像 |
ADD |
复制文件(支持 URL 和自动解压) |
RUN |
构建时执行命令 |
CMD |
容器启动时的默认命令(可被覆盖) |
ENTRYPOINT |
容器启动命令(不会被覆盖) |
ENV |
环境变量 |
ARG |
构建参数 |
EXPOSE |
声明端口 |
VOLUME |
声明数据卷挂载点 |
多阶段构建
1 2 3 4 5 6 7 8 9 10 11 12 13
| FROM maven:3.9-eclipse-temurin-17 AS builder WORKDIR /app COPY pom.xml . COPY src ./src RUN mvn clean package -DskipTests
FROM eclipse-temurin:17-jre-alpine WORKDIR /app COPY --from=builder /app/target/*.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]
|
最佳实践
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| FROM node:20-alpine
RUN apk add --no-cache git curl \ && npm install \ && npm cache clean --force
COPY package.json package-lock.json ./ RUN npm ci COPY . .
RUN addgroup -S app && adduser -S app -G app USER app
|
六、Docker Compose
docker-compose.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| version: '3.8'
services: app: build: . ports: - "8080:8080" environment: - SPRING_PROFILES_ACTIVE=prod - DB_HOST=mysql - DB_PORT=3306 - DB_NAME=mydb - DB_PASSWORD=secret depends_on: mysql: condition: service_healthy restart: unless-stopped networks: - app-net
mysql: image: mysql:8.0 ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: secret MYSQL_DATABASE: mydb volumes: - mysql-data:/var/lib/mysql - ./init.sql:/docker-entrypoint-initdb.d/init.sql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped networks: - app-net
redis: image: redis:7-alpine ports: - "6379:6379" volumes: - redis-data:/data restart: unless-stopped networks: - app-net
nginx: image: nginx:1.24-alpine ports: - "80:80" - "443:443" volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro - ./ssl:/etc/nginx/ssl:ro depends_on: - app restart: unless-stopped networks: - app-net
volumes: mysql-data: redis-data:
networks: app-net: driver: bridge
|
常用命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| docker compose up -d
docker compose ps
docker compose logs -f app
docker compose down
docker compose down -v
docker compose up -d --build
docker compose up -d --scale app=3
|
七、常用服务部署
MySQL
1 2 3 4 5 6 7 8 9
| docker run -d \ --name mysql \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=secret \ -e MYSQL_DATABASE=mydb \ -v mysql-data:/var/lib/mysql \ mysql:8.0 \ --character-set-server=utf8mb4 \ --collation-server=utf8mb4_unicode_ci
|
Redis
1 2 3 4 5 6
| docker run -d \ --name redis \ -p 6379:6379 \ -v redis-data:/data \ redis:7-alpine \ redis-server --appendonly yes --requirepass mypassword
|
Nginx
1 2 3 4 5 6 7
| docker run -d \ --name nginx \ -p 80:80 \ -p 443:443 \ -v ./nginx.conf:/etc/nginx/nginx.conf:ro \ -v ./html:/usr/share/nginx/html:ro \ nginx:1.24-alpine
|
PostgreSQL
1 2 3 4 5 6 7
| docker run -d \ --name postgres \ -p 5432:5432 \ -e POSTGRES_PASSWORD=secret \ -e POSTGRES_DB=mydb \ -v pg-data:/var/lib/postgresql/data \ postgres:16-alpine
|
八、生产实践
镜像安全
1 2 3 4 5 6 7 8 9
| docker scout cves nginx:1.24
FROM alpine:3.19 FROM scratch
docker run --read-only --tmpfs /tmp my-app:1.0
|
资源限制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| docker run -m 512m my-app:1.0
docker run --cpus=1.5 my-app:1.0
services: app: deploy: resources: limits: cpus: '1.5' memory: 512M reservations: memory: 256M
|
日志管理
1 2 3 4 5 6 7 8
| { "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } }
|
健康检查
1 2
| HEALTHCHECK --interval=30s --timeout=3s --retries=3 \ CMD curl -f http://localhost:8080/health || exit 1
|
1 2
| docker inspect --format='{{.State.Health.Status}}' my-app
|
九、常用命令速查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| docker version docker info docker system df
docker system prune docker system prune -a docker system prune --volumes
docker export my-nginx > nginx.tar docker import nginx.tar my-nginx:imported
docker stats docker stats --no-stream
docker cp my-nginx:/etc/nginx/nginx.conf ./nginx.conf docker cp ./app.jar my-app:/app/app.jar
|
总结
Docker 通过容器化技术实现了”构建一次,到处运行”。核心技能包括 Dockerfile 编写、镜像构建、容器管理和 Docker Compose 编排。在生产环境中,注意镜像安全、资源限制和日志管理。Docker 是学习 Kubernetes 的基础,建议先熟练掌握再进入编排领域。