Home / 实用工具 / 2026.04.24

Docker 与 Docker Compose:从零理解容器化,一条命令编排整个应用栈

Docker Engine 71.5K Star,Docker Compose 37.3K Star。容器让应用跑在隔离环境里,Compose 让多容器应用一条命令启动。从概念到安装,从 Dockerfile 到 compose.yaml,一篇搞懂容器化开发的核心工具链。

Docker Engine GitHub 71.5K Star,Docker Compose GitHub 37.3K Star——这是容器化生态的基石。Docker 解决”应用怎么跑”,Compose 解决”多个应用怎么一起跑”。两者配合,一条命令就能启动包含 Web 服务器、数据库、缓存的完整应用栈。

Docker 官网:docker.com · Engine 仓库:github.com/moby/moby · Compose 仓库:github.com/docker/compose · 文档:docs.docker.com

先搞清楚概念

什么是容器

容器是一个隔离的运行环境,里面只有你的应用和它的依赖——没有操作系统内核,没有多余的系统服务。它共享宿主机的内核,但文件系统、网络、进程都是隔离的。

维度虚拟机容器
隔离级别硬件级(完整 OS)进程级(共享内核)
启动速度分钟级秒级
磁盘占用GB 级MB 级
性能损耗有虚拟化开销接近原生
适用场景强隔离需求微服务、CI/CD、开发环境

容器不是轻量级虚拟机——它不模拟硬件,不运行完整操作系统。容器就是一个被隔离的进程,跑在宿主机内核上,但看起来像独占了一台机器。

什么是镜像

镜像是容器的只读模板。你把应用代码、运行环境、依赖库全部打包成一个镜像,然后在任何机器上用这个镜像启动容器——环境一致性问题就此解决。

Docker 做了什么

Docker 做了三件事:

  1. 构建镜像:用 Dockerfile 定义如何打包应用
  2. 分发镜像:通过 Docker Hub 等镜像仓库共享镜像
  3. 运行容器:从镜像启动隔离的运行环境

Docker Compose 做了什么

Docker 管单个容器,Compose 管多个容器。一个典型 Web 应用需要 Nginx + Node.js + MySQL + Redis 四个服务,用 Docker 你得手动启动四个容器、配网络、挂载卷。用 Compose,写一个 YAML 文件,一条命令全部启动。

安装

Docker Engine(Linux 服务器)

支持 Ubuntu、Debian、CentOS、RHEL、Fedora 等主流发行版。

Ubuntu/Debian 一键安装:

# 官方安装脚本(最简单)
curl -fsSL https://get.docker.com | sudo sh

# 将当前用户加入 docker 组(免 sudo)
sudo usermod -aG docker $USER
newgrp docker

CentOS/RHEL:

# 同样使用官方脚本
curl -fsSL https://get.docker.com | sudo sh
sudo systemctl enable --now docker

安装完成后验证:

docker --version      # Docker version 29.x.x
docker compose version # Docker Compose version v5.x.x
docker run hello-world # 测试运行

Docker Compose v2 已内置在 Docker Engine 中,作为 CLI 插件运行,使用 docker compose(无横线)。旧版独立 docker-compose(Python 版)已停止维护。

Docker Desktop(Mac / Windows / Linux 桌面)

Docker Desktop 是 Docker 的桌面版,包含 Docker Engine + Compose + Kubernetes + GUI 管理界面。

平台安装方式
macOSdocker.com/products/docker-desktop 下载 DMG
Windows同上,下载安装包(需 WSL2)
Linux同上,下载 DEB/RPM 包
版本价格说明
Personal免费个人、小企业(<250 员工 且 收入 <$1000 万)
Pro$5/月/人个人开发者高级功能
Team$9/月/人团队协作
Business$24/月/人企业级安全和管理

大企业(>250 员工或年收入 >$1000 万)使用 Docker Desktop 需要付费订阅。Docker Engine 本身是开源的(Apache-2.0),不受此限制。

核心概念

Dockerfile:定义镜像

Dockerfile 是构建镜像的”配方”,从基础镜像开始,一层一层叠加:

# 基础镜像
FROM node:20-alpine

# 设置工作目录
WORKDIR /app

# 复制依赖文件并安装
COPY package*.json ./
RUN npm ci --only=production

# 复制应用代码
COPY . .

# 暴露端口
EXPOSE 3000

# 启动命令
CMD ["node", "server.js"]
指令作用
FROM基础镜像
WORKDIR容器内工作目录
COPY复制文件到容器
RUN构建时执行命令
ENV设置环境变量
EXPOSE声明端口(文档作用)
CMD容器启动命令
ENTRYPOINT容器入口点

构建镜像:

docker build -t myapp:v1 .

镜像管理

docker images                    # 查看本地镜像
docker pull nginx:latest         # 拉取镜像
docker push myrepo/myapp:v1      # 推送镜像
docker rmi myapp:v1              # 删除镜像

容器生命周期

docker run -d -p 3000:3000 --name myapp myapp:v1  # 创建并启动
docker ps                                         # 查看运行中容器
docker stop myapp                                 # 停止
docker start myapp                                # 启动
docker restart myapp                              # 重启
docker rm myapp                                   # 删除
docker logs myapp                                 # 查看日志
docker exec -it myapp sh                          # 进入容器
参数作用
-d后台运行
-p 3000:3000端口映射(宿主:容器)
—name myapp容器命名
-v /host:/container挂载卷
-e KEY=VALUE环境变量
—restart unless-stopped自动重启策略

数据持久化

容器删除后数据就没了。持久化数据用 Volume 或 Bind Mount:

方式命令特点
Volume-v mydata:/var/lib/mysqlDocker 管理,推荐
Bind Mount-v /home/data:/var/lib/mysql绑定宿主目录
tmpfs--tmpfs /tmp内存存储,容器停止即消失

网络

docker network create mynet                    # 创建网络
docker run -d --network mynet --name app ...   # 容器加入网络

同一网络内的容器可以用容器名互相访问——不需要知道对方的 IP。

Docker Compose 详解

compose.yaml 结构

services:
  web:
    build: .
    ports:
      - "3000:3000"
    environment:
      - DB_HOST=db
      - REDIS_HOST=redis
    depends_on:
      - db
      - redis
    volumes:
      - .:/app
    restart: unless-stopped

  db:
    image: mysql:8
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: myapp
    volumes:
      - db_data:/var/lib/mysql
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    restart: unless-stopped

volumes:
  db_data:
字段作用
services定义各个服务(容器)
build从 Dockerfile 构建
image直接使用镜像
ports端口映射
environment环境变量
depends_on启动依赖顺序
volumes数据卷挂载
restart重启策略
networks网络配置

Compose 常用命令

docker compose up -d          # 启动所有服务(后台)
docker compose down           # 停止并删除所有容器
docker compose ps             # 查看服务状态
docker compose logs -f web    # 跟踪 web 服务日志
docker compose exec db bash   # 进入 db 容器
docker compose build          # 重新构建镜像
docker compose pull           # 拉取最新镜像
docker compose restart web    # 重启单个服务
docker compose up -d --build  # 重新构建并启动

实战:完整 Web 应用

一个 Node.js + MySQL + Redis + Nginx 的完整项目结构:

project/
├── compose.yaml
├── web/
│   ├── Dockerfile
│   ├── package.json
│   └── server.js
└── nginx/
    └── default.conf

compose.yaml:

services:
  web:
    build: ./web
    environment:
      - DB_HOST=db
      - REDIS_HOST=redis
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    restart: unless-stopped

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - web
    restart: unless-stopped

  db:
    image: mysql:8
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
      MYSQL_DATABASE: myapp
    volumes:
      - db_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    volumes:
      - redis_data:/data
    restart: unless-stopped

volumes:
  db_data:
  redis_data:

启动:

docker compose up -d

一条命令,四个服务全部启动,网络自动配置,依赖自动管理。

Compose Watch(开发热重载)

Compose v2.22+ 支持文件监听自动同步:

services:
  web:
    build: .
    develop:
      watch:
        - action: sync
          path: ./src
          target: /app/src
        - action: rebuild
          path: ./package.json
docker compose watch  # 启动监听模式

修改本地代码自动同步到容器,改 package.json 自动重新构建——不需要手动重启。

Docker vs Podman vs Nix

维度DockerPodmanNix
Star71.5K26K+18K+
架构客户端-服务端(daemon)无 daemon声明式包管理
Root 权限默认需要不需要(rootless)不需要
Compose原生支持兼容(podman-compose)
镜像兼容Docker HubDocker HubNix Store
生态最成熟Red Hat 推动Nix 社区
学习曲线低(Docker 兼容)

Podman 是 Docker 的主要替代品——无需 daemon、默认 rootless、命令行语法兼容 Docker。但对于大多数人和团队,Docker 的生态成熟度和文档覆盖面仍然是选择它的理由。

容器化最佳实践

实践说明
使用多阶段构建构建阶段用完整镜像,运行阶段用精简镜像,最终镜像体积小 10 倍
固定镜像版本node:20-alpine 而不是 node:latest,避免不可控变更
使用 .dockerignore排除 node_modules、.git 等,加速构建
一个容器一个进程不要在一个容器里跑 Nginx + Node.js
善用健康检查healthcheck 让 Docker 知道容器是否真的健康
不在镜像里存密钥用环境变量或 Docker Secrets 传入
合理利用缓存Dockerfile 中把不常变的层(npm install)放前面

多阶段构建示例:

# 构建阶段
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# 运行阶段(只有构建产物,没有源码和 devDependencies)
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/server.js"]

常用镜像选择

用途推荐镜像大小
Node.jsnode:20-alpine~180 MB
Pythonpython:3.12-slim~150 MB
Gogolang:1.22-alpine~300 MB(构建用)
Nginxnginx:alpine~40 MB
MySQLmysql:8~580 MB
PostgreSQLpostgres:16-alpine~230 MB
Redisredis:7-alpine~40 MB
Alpinealpine:3.19~7 MB

-alpine 后缀表示基于 Alpine Linux 的精简版,体积远小于标准版。生产环境推荐优先选择 alpine 变体,除非有 glibc 兼容性问题。

写在最后

Docker 改变的不仅是部署方式——它改变了软件交付的整个链路。开发者用 Dockerfile 定义环境,用 Compose 编排服务,CI/CD 用镜像做交付件,运维用容器做编排。从”在我机器上能跑”到”在容器里能跑”,环境一致性问题被彻底解决。

Docker 解决的核心问题只有一个:环境一致性。从开发机到测试环境到生产服务器,同一个镜像跑出来的行为完全一致。Compose 在此基础上解决第二个问题:多服务编排。两者配合,才是容器化开发的完整答案。