上一篇 下一篇 分享链接 返回 返回顶部

Docker 和 Docker Compose 到底差在哪?一文讲清用法和配置

发布人:慈云数据-客服中心 发布时间:11小时前 阅读量:4

Docker 和 Docker 的区别|附配置文件

说明:很多人在搜索或写标题时,会把“Docker 和 Docker Compose 的区别”误写成“Docker 和 Docker 的区别”。从实际使用场景来看,开发者通常想了解的是 Docker 与 Docker Compose 的区别,以及它们各自应该如何配置和使用。本文将围绕这个方向展开,并附上常见配置文件示例。


一、什么是 Docker?

Docker 是一种容器化技术平台,它可以把应用程序及其运行环境打包成一个独立的容器,让应用可以在不同机器、不同系统环境中保持一致运行。

简单来说,Docker 解决的是这样一个问题:

“为什么我本地能跑,到了服务器就跑不起来?”

在传统部署方式中,一个应用可能依赖:

  • 操作系统版本
  • JDK / Node.js / Python / PHP 等运行环境
  • 系统库文件
  • 环境变量
  • 配置文件
  • 数据库连接
  • 端口配置

如果开发环境和生产环境存在差异,就很容易出现各种兼容性问题。

Docker 的核心思想是:
把应用和运行环境一起打包,形成镜像,然后基于镜像启动容器。


二、Docker 的核心概念

在理解 Docker 和 Docker Compose 的区别之前,需要先掌握 Docker 中几个重要概念。

1. 镜像 Image

镜像可以理解为一个只读模板,里面包含应用程序、依赖环境、系统库、配置等内容。

例如:

nginx:latest
mysql:8.0
redis:7
node:20
openjdk:17

这些都是常见镜像。

你可以通过以下命令拉取镜像:

docker pull nginx:latest

查看本地镜像:

docker images

2. 容器 Container

容器是镜像运行起来之后的实例。

镜像类似“类”,容器类似“对象”。

例如基于 Nginx 镜像启动一个容器:

docker run -d \
  --name my-nginx \
  -p 8080:80 \
  nginx:latest

含义如下:

参数 说明
-d 后台运行
--name my-nginx 指定容器名称
-p 8080:80 将宿主机 8080 端口映射到容器 80 端口
nginx:latest 使用的镜像

启动后访问:

http://localhost:8080

就可以看到 Nginx 页面。


3. Dockerfile

Dockerfile 是用来构建 Docker 镜像的配置文件。

例如,一个 Node.js 项目的 Dockerfile 可以这样写:

FROM node:20-alpine

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 3000

CMD ["npm", "run", "start"]

它的作用是:

  1. 使用 node:20-alpine 作为基础镜像;
  2. 设置工作目录为 /app
  3. 复制依赖文件;
  4. 安装依赖;
  5. 复制项目代码;
  6. 暴露 3000 端口;
  7. 启动应用。

构建镜像:

docker build -t my-node-app:1.0 .

运行容器:

docker run -d \
  --name node-app \
  -p 3000:3000 \
  my-node-app:1.0

三、什么是 Docker Compose?

Docker Compose 是 Docker 官方提供的一个多容器编排工具。

如果说 Docker 更偏向于管理单个容器,那么 Docker Compose 更适合管理一组容器。

在实际项目中,一个完整系统通常不只有一个应用容器,例如:

  • 后端服务
  • 前端服务
  • MySQL 数据库
  • Redis 缓存
  • Nginx 网关
  • RabbitMQ 消息队列
  • Elasticsearch 搜索服务

如果只使用 Docker 命令,每个服务都需要写一大串 docker run 命令:

docker run -d --name mysql ...
docker run -d --name redis ...
docker run -d --name backend ...
docker run -d --name nginx ...

当服务数量变多时,管理起来会非常麻烦。

Docker Compose 的作用就是:

用一个 docker-compose.yml 文件描述多个容器,并通过一条命令统一启动、停止和管理。


四、Docker 和 Docker Compose 的区别

下面通过表格对比二者区别。

对比项 Docker Docker Compose
定位 容器化平台 多容器编排工具
管理对象 镜像、容器、网络、卷等 多个服务组成的应用
常用文件 Dockerfile docker-compose.yml
使用方式 命令行操作单个容器较多 配置文件统一管理多个容器
适用场景 构建镜像、运行单容器 本地开发、测试环境、中小型部署
启动命令 docker run docker compose up
配置复杂度 参数多时命令较长 配置集中,更易维护
是否替代关系 不是 基于 Docker 工作

需要注意:

Docker Compose 并不是 Docker 的替代品,而是 Docker 的补充工具。

Docker Compose 底层仍然依赖 Docker。
没有 Docker,Docker Compose 无法单独运行。


五、一个简单例子:只使用 Docker 启动 MySQL

假设我们要启动一个 MySQL 8.0 容器,如果使用 Docker 命令,可以这样写:

docker run -d \
  --name mysql8 \
  -p 3306:3306 \
  -e MYSQL_ROOT_PASSWORD=123456 \
  -e MYSQL_DATABASE=test_db \
  -v mysql_data:/var/lib/mysql \
  mysql:8.0

这个命令包含了:

  • 容器名称
  • 端口映射
  • 环境变量
  • 数据卷挂载
  • 镜像版本

虽然这个例子还不算复杂,但如果参数继续增加,命令会越来越长,可读性和维护性都会下降。


六、使用 Docker Compose 启动 MySQL

如果使用 Docker Compose,可以创建一个 docker-compose.yml 文件:

services:
  mysql:
    image: mysql:8.0
    container_name: mysql8
    restart: always
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE: test_db
      TZ: Asia/Shanghai
    volumes:
      - mysql_data:/var/lib/mysql
    command:
      --default-authentication-plugin=mysql_native_password

volumes:
  mysql_data:

然后执行:

docker compose up -d

停止服务:

docker compose down

查看日志:

docker compose logs -f mysql

相比一长串命令,Compose 配置文件更清晰,也更适合团队协作和版本管理。


七、完整项目示例:后端 + MySQL + Redis

下面给出一个更接近实际项目的配置示例。

项目结构如下:

demo-project
├── backend
│   ├── Dockerfile
│   ├── package.json
│   └── src
│       └── index.js
├── docker-compose.yml
└── .env

八、后端服务 Dockerfile 配置

假设后端是一个 Node.js 服务,可以在 backend/Dockerfile 中写入:

FROM node:20-alpine

WORKDIR /app

COPY package*.json ./

RUN npm install --registry=https://registry.npmmirror.com

COPY . .

EXPOSE 3000

CMD ["npm", "run", "start"]

这个 Dockerfile 用于构建后端镜像。

如果你的后端是 Java Spring Boot,也可以使用类似配置:

FROM openjdk:17-jdk-slim

WORKDIR /app

COPY target/app.jar app.jar

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "app.jar"]

如果是 Go 项目,也可以采用多阶段构建:

FROM golang:1.22-alpine AS builder

WORKDIR /app

COPY . .

RUN go build -o server main.go

FROM alpine:latest

WORKDIR /app

COPY --from=builder /app/server .

EXPOSE 8080

CMD ["./server"]

不同语言的 Dockerfile 写法不完全相同,但核心思路一致:

  1. 选择基础镜像;
  2. 设置工作目录;
  3. 复制代码和依赖文件;
  4. 安装依赖或编译项目;
  5. 暴露端口;
  6. 设置启动命令。

九、docker-compose.yml 配置文件

下面是一个后端服务、MySQL、Redis 同时启动的配置:

services:
  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    container_name: demo-backend
    restart: always
    ports:
      - "3000:3000"
    environment:
      NODE_ENV: production
      DB_HOST: mysql
      DB_PORT: 3306
      DB_NAME: demo_db
      DB_USER: root
      DB_PASSWORD: 123456
      REDIS_HOST: redis
      REDIS_PORT: 6379
      TZ: Asia/Shanghai
    depends_on:
      - mysql
      - redis
    networks:
      - demo-net

  mysql:
    image: mysql:8.0
    container_name: demo-mysql
    restart: always
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE: demo_db
      TZ: Asia/Shanghai
    volumes:
      - mysql_data:/var/lib/mysql
      - ./mysql/conf:/etc/mysql/conf.d
      - ./mysql/init:/docker-entrypoint-initdb.d
    command:
      --default-authentication-plugin=mysql_native_password
      --character-set-server=utf8mb4
      --collation-server=utf8mb4_unicode_ci
    networks:
      - demo-net

  redis:
    image: redis:7-alpine
    container_name: demo-redis
    restart: always
    ports:
      - "6379:6379"
    command:
      redis-server --requirepass 123456 --appendonly yes
    volumes:
      - redis_data:/data
    networks:
      - demo-net

volumes:
  mysql_data:
  redis_data:

networks:
  demo-net:
    driver: bridge

这个配置文件中定义了三个服务:

  • backend:后端应用;
  • mysql:数据库;
  • redis:缓存服务。

其中,backend 服务通过 DB_HOST: mysql 连接数据库,通过 REDIS_HOST: redis 连接 Redis。

这是 Docker Compose 中非常重要的特性:

同一个 Compose 网络中的服务,可以通过服务名互相访问。

也就是说,后端应用不需要写 MySQL 容器的 IP 地址,只需要写服务名 mysql


十、使用 .env 管理环境变量

在实际项目中,不建议把密码、端口等配置全部硬编码在 docker-compose.yml 中。
可以使用 .env 文件统一管理。

.env 示例:

APP_PORT=3000

MYSQL_ROOT_PASSWORD=123456
MYSQL_DATABASE=demo_db
MYSQL_PORT=3306

REDIS_PASSWORD=123456
REDIS_PORT=6379

TZ=Asia/Shanghai

然后改造 docker-compose.yml

services:
  backend:
    build:
      context: ./backend
    container_name: demo-backend
    restart: always
    ports:
      - "${APP_PORT}:3000"
    environment:
      NODE_ENV: production
      DB_HOST: mysql
      DB_PORT: 3306
      DB_NAME: ${MYSQL_DATABASE}
      DB_USER: root
      DB_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      REDIS_HOST: redis
      REDIS_PORT: 6379
      REDIS_PASSWORD: ${REDIS_PASSWORD}
      TZ: ${TZ}
    depends_on:
      - mysql
      - redis
    networks:
      - demo-net

  mysql:
    image: mysql:8.0
    container_name: demo-mysql
    restart: always
    ports:
      - "${MYSQL_PORT}:3306"
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      TZ: ${TZ}
    volumes:
      - mysql_data:/var/lib/mysql
    networks:
      - demo-net

  redis:
    image: redis:7-alpine
    container_name: demo-redis
    restart: always
    ports:
      - "${REDIS_PORT}:6379"
    command:
      redis-server --requirepass ${REDIS_PASSWORD} --appendonly yes
    volumes:
      - redis_data:/data
    networks:
      - demo-net

volumes:
  mysql_data:
  redis_data:

networks:
  demo-net:
    driver: bridge

这样做的好处是:

  1. 配置更加清晰;
  2. 不同环境可以使用不同 .env 文件;
  3. 敏感信息更容易统一管理;
  4. Compose 文件更通用。

需要注意的是,如果项目上传到 Git 仓库,建议不要直接提交真实的 .env 文件,而是提交 .env.example

例如:

APP_PORT=3000

MYSQL_ROOT_PASSWORD=your_password
MYSQL_DATABASE=your_database
MYSQL_PORT=3306

REDIS_PASSWORD=your_redis_password
REDIS_PORT=6379

TZ=Asia/Shanghai

十一、Docker Compose 常用命令

1. 启动服务

docker compose up -d

-d 表示后台运行。


2. 停止并删除容器

docker compose down

如果想同时删除数据卷:

docker compose down -v

注意:
-v 会删除数据卷,数据库数据可能会丢失,生产环境慎用。


3. 查看服务状态

docker compose ps

4. 查看日志

查看全部日志:

docker compose logs -f

查看某个服务日志:

docker compose logs -f backend

5. 重新构建镜像并启动

docker compose up -d --build

当后端代码或 Dockerfile 修改后,通常需要执行这个命令。


6. 进入容器

docker exec -it demo-backend sh

如果容器内是 Debian 或 Ubuntu 系统,也可以使用:

docker exec -it demo-backend bash

7. 删除未使用资源

docker system prune

如果要删除未使用镜像、容器、网络和构建缓存:

docker system prune -a

该命令也要谨慎使用,避免误删仍需要的镜像。


十二、什么时候用 Docker,什么时候用 Docker Compose?

适合直接使用 Docker 的场景

如果只是临时启动一个单独服务,例如:

  • 启动一个 Nginx 测试页面;
  • 启动一个 Redis 做临时测试;
  • 构建某个应用镜像;
  • 查看容器运行状态;
  • 调试单个容器。

这时候直接使用 Docker 命令即可。

例如:

docker run -d --name redis-test -p 6379:6379 redis:7-alpine

这种方式简单直接。


适合使用 Docker Compose 的场景

如果你的项目包含多个服务,例如:

  • Web 应用 + MySQL;
  • 后端服务 + Redis;
  • 前端 + 后端 + 数据库;
  • 微服务项目;
  • 本地开发环境;
  • 测试环境部署。

这时更推荐使用 Docker Compose。

因为它可以把所有服务关系都写进一个配置文件中,方便启动、停止、迁移和维护。


十三、常见误区

误区一:Docker Compose 可以替代 Docker

不可以。

Docker Compose 是基于 Docker 的工具,它调用 Docker 引擎来创建和管理容器。
如果没有 Docker,Compose 不能独立完成容器运行。


误区二:Dockerfile 和 docker-compose.yml 是同一个东西

不是。

二者作用不同:

文件 作用
Dockerfile 描述如何构建镜像
docker-compose.yml 描述如何运行多个服务

Dockerfile 关注的是“镜像怎么做”。
docker-compose.yml 关注的是“容器怎么跑”。


误区三:有了 Compose 就不用写 Dockerfile

不一定。

如果你使用的是官方镜像,例如 MySQL、Redis、Nginx,可以不写 Dockerfile,直接在 Compose 中指定镜像。

但如果你要运行自己的业务代码,比如 Java、Node.js、Go、Python 项目,通常仍然需要 Dockerfile 来构建自定义镜像。


误区四:depends_on 能保证数据库完全启动成功

depends_on 只能保证容器启动顺序,不能保证服务已经完全可用。

例如 MySQL 容器启动了,但数据库初始化还没完成,后端应用立即连接可能会失败。

更稳妥的做法是:

  • 应用自身增加重试机制;
  • 使用健康检查 healthcheck
  • 在启动脚本中等待服务可用。

示例:

services:
  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE: demo_db
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-p123456"]
      interval: 10s
      timeout: 5s
      retries: 5

十四、生产环境使用建议

Docker Compose 可以用于中小型项目部署,但在生产环境中需要注意以下几点:

  1. 不要使用弱密码
    示例中的 123456 仅用于演示,生产环境必须使用高强度密码。

  2. 不要随意暴露数据库端口
    如果后端和数据库都在同一 Docker 网络中,MySQL 不一定需要映射到宿主机端口。

  3. 做好数据卷备份
    MySQL、Redis 等有状态服务需要定期备份数据。

  4. 固定镜像版本
    不建议生产环境使用 latest,最好指定明确版本,例如 mysql:8.0.36

  5. 配置日志策略
    避免容器日志无限增长,占满磁盘。

示例:

logging:
  driver: json-file
  options:
    max-size: "100m"
    max-file: "3"
  1. 区分开发、测试、生产配置
    可以使用多个 Compose 文件,例如:
docker-compose.yml
docker-compose.dev.yml
docker-compose.prod.yml

启动生产配置:

docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

十五、总结

如果用一句话总结 Docker 和 Docker Compose 的区别:

Docker 负责容器化,Docker Compose 负责把多个容器组织起来一起运行。

更具体地说:

  • Docker 主要用于构建镜像、运行容器、管理镜像和容器资源;
  • Dockerfile 用于描述镜像构建过程;
  • Docker Compose 用于通过配置文件管理多个服务;
  • docker-compose.yml 用于描述服务、网络、数据卷、环境变量和依赖关系。

在单容器场景下,直接使用 Docker 命令即可。
在多服务项目中,推荐使用 Docker Compose,因为它更清晰、更易维护,也更适合团队协作。

对于日常开发来说,最佳实践通常是:

  1. 使用 Dockerfile 构建业务服务镜像;
  2. 使用 docker-compose.yml 编排应用、数据库、缓存等服务;
  3. 使用 .env 管理环境变量;
  4. 使用数据卷持久化重要数据;
  5. 使用固定版本镜像保证环境稳定;
  6. 在生产环境中加强安全、备份和日志管理。

掌握 Docker 与 Docker Compose 的区别之后,就能更合理地设计项目部署方案,让开发、测试和上线流程更加统一、稳定和高效。

目录结构
全文