初识Docker,入门篇及实战操作

🐳 什么是 Docker?

Docker 是一个能让我们"打包 + 运输 + 运行"程序的工具。可以理解为就像现实中我们会用 集装箱 来运货,Docker 就是程序的集装箱

📦 举个超级通俗的例子:

假设你做了一个很好用的 Node.js 网站,别人想用它,但有问题:

• 别人电脑没有 Node.js ❌

• 别人系统是 Windows,你的是 Mac ❌

• 别人不会配置环境 ❌

你就会心累😩。

这时候你把整个项目打包成一个 Docker 镜像,别人只需要一行命令:

bash 复制代码
docker run xxx

什么都不用装、跨平台、开箱即用,**运行效果 100% 跟你一模一样!**✅✅

🎁 Docker 三个核心概念

  1. 镜像 (image):(冷冻快餐)打包好的程序,里面包括代码、运行环境、依赖
  2. 容器 (container):(微波炉热好的饭)镜像运行起来就变成了容器,是你可以访问、操作的"活"程序
  3. Dockerfile:(菜谱)告诉 Docker 怎么做一份镜像(从哪下载,装啥依赖,复制啥文件等)

Docker 命令总览

🎁 小抄级总结 最常用的组合命令是:

bash 复制代码
# 构建镜像
docker build -t myapp .

# 运行容器
docker run -p 3000:3000 myapp

# 停止容器
docker stop 容器名

# 启动 compose
docker compose up -d

🛠 举个完整例子:

bash 复制代码
docker run -it --rm --name myweb -p 8080:80 nginx

这个命令的意思是:

• 启动一个 nginx 容器

• 映射端口:本地 8080 → 容器 80

• 容器名字叫 myweb

• 启动时是交互模式(-it)

• 退出时自动删除(--rm)


⚙️ docker run 命令常用参数(容器运行控制)

命名片段 作用
-it 用于调试或交互进容器
-d 后台运行
--rm 用完即焚
--name xxx 容器好找
-p 端口映射 让服务暴露给本地访问
-v 卷挂载 数据不丢,代码同步

Dockerfile 和 Docker Compose

  • Dockerfile:是 "造快餐" 的说明书(构建镜像),每一条指令(FROM、COPY、RUN)都是一步操作。Docker 会按照这个文件的内容,一步一步构建出镜像。
md 复制代码
负责:定义单个服务的构建过程(怎么打包成镜像)
文件名固定:Dockerfile(没有后缀)
##运行你自己写的 Dockerfile 构建出来的镜像
# 先构建镜像,运行规则
docker build [-t=给构建出来的镜像起名字] [镜像名] [-f:指定一个非默认名字的 Dockerfile] [构建上下文路径, 代码+Dockerfile 所在目录]
docker build -t my-app -f Dockerfile.dev .
# 然后运行
docker run -p 3000:3000 my-app
示例Dockerfile 复制代码
# 阶段1:使用 Node 镜像
FROM node:20

# 设置工作目录
WORKDIR /app

# 拷贝依赖文件并安装依赖(加缓存优化)
COPY package*.json yarn.lock ./
RUN yarn install

# 拷贝代码
COPY . .

# 设置环境变量
ENV NODE_ENV=development

# 开放开发端口(vite 默认 300)
EXPOSE 3001

# 默认执行开发命令
CMD ["yarn", "dev"]
  • docker-compose.yml: 是 "如何安排这顿饭"的菜单(启动容器), 用来描述、定义、运行多个容器服务的组合。
md 复制代码
# 文件名通常是:docker-compose.yml
# 运行指令:
(默认文件名):docker compose up -d   (docker-compose.yml的运行方式)
非默认文件名):docker compose -f [文件名].yml up -d 
## 🧱 顶级命令结构
docker compose -f docker-compose.dev.yml up --force-recreate

docker compose <一级子命令> [一级子命令参数] <二级子命令> [二级子命令参数]


⚙️ 一级子命令参数(Compose CLI 全局参数)

参数 示例 用途 说明
-f -f docker-compose.dev.yml 指定配置文件(可多个)
--env-file --env-file .env.dev 加载额外的环境变量文件
--project-name --project-name my-app 自定义项目名(默认当前文件夹名)
--profile --profile debug 启用指定的 profile(服务分组)
--compatibility --compatibility 启用旧版 v2 行为兼容模式
--ansi --ansi never 控制颜色输出:auto / always / never
--no-ansi --no-ansi 禁用彩色输出(等于 --ansi never
--parallel --parallel 3 限制同时构建/拉取服务数量
--log-level --log-level ERROR 设置 CLI 日志级别:DEBUG / INFO / ERROR

🧰 二级子命令参数(作用于 up

参数 示例 说明
-d / --detach up -d 后台运行容器
--build up --build 启动前自动构建镜像
--force-recreate up --force-recreate 强制重建容器
--no-build up --no-build 禁止构建镜像
--no-recreate up --no-recreate 禁止重建容器
--remove-orphans up --remove-orphans 删除非当前文件定义的容器
--wait up --wait 等待服务启动完毕才返回
--quiet-pull up --quiet-pull 静默拉取镜像

🔻 二级子命令参数(作用于 down

参数 示例 说明
--volumes down --volumes 同时删除数据卷
--remove-orphans down --remove-orphans 删除孤立容器
--timeout down --timeout 5 停止前等待时间(秒)

📦 二级子命令参数(作用于 logs

参数 示例 说明
-f / --follow logs -f 实时日志
--tail logs --tail=100 查看末尾 N 行日志
--timestamps logs --timestamps 显示时间戳
--no-color logs --no-color 关闭颜色高亮

📋 二级子命令参数(作用于 ps

参数 示例 说明
--services ps --services 仅显示服务名
--quiet ps --quiet 仅显示容器 ID

🔧 二级子命令参数(作用于 build

参数 示例 说明
--no-cache build --no-cache 不使用缓存
--pull build --pull 总是拉取镜像
--progress build --progress=plain 控制构建日志格式

✅ 适合搭配 up, down, logs, ps, build 命令灵活组合使用!

Compose 文件是 启动多个容器时的一张"总布置图

它定义:

• 哪些服务(容器)要运行?

• 用哪个镜像或 Dockerfile?

• 启用哪些端口、挂载哪些目录?

• 它们之间的依赖关系是怎样?

一套通用的配置结构

完整docker-compose.yml 配置

docker-compose.yaml 复制代码
version: '3.9'

services:
  # -------------------------------
  # 🌐 前端服务(React / Vite 项目)
  # -------------------------------
  web:
    build: ./web                            # 使用当前目录下 ./web 的 Dockerfile 构建镜像
    container_name: web_app                 # 自定义容器名,方便调试和识别
    ports:
      - "3000:3000"                          # 将本机 3000 端口映射到容器内 3000
    depends_on:
      - api                                 # 等待 api 服务就绪再启动(只是顺序,不是就绪检测)
    environment:
      - NODE_ENV=development                # 传入环境变量
    volumes:
      - ./web:/app                          # 挂载本地项目到容器,支持热更新(前提:框架支持)
    networks:
      - frontend

  # -------------------------------
  # 🧩 后端服务(Node.js API 项目)
  # -------------------------------
  api:
    build: ./api
    container_name: api_server
    ports:
      - "4000:4000"
    depends_on:
      - db
      - redis
    environment:
      - DB_HOST=db                          # DB 容器的服务名作为主机名
      - DB_PORT=5432
      - DB_USER=user
      - DB_PASSWORD=password
      - DB_NAME=appdb
      - REDIS_HOST=redis                    # Redis 容器的服务名
      - REDIS_PORT=6379
    volumes:
      - ./api:/app
    networks:
      - frontend
      - backend

  # -------------------------------
  # 🗃️ 数据库服务(PostgreSQL)
  # -------------------------------
  db:
    image: postgres:14
    container_name: postgres_db
    restart: always                         # 容器异常退出时自动重启
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: appdb
    volumes:
      - db_data:/var/lib/postgresql/data    # 持久化数据库数据
    ports:
      - "5432:5432"                          # 可选:方便用本地工具连接调试
    networks:
      - backend

  # -------------------------------
  # 🚀 缓存服务(Redis)
  # -------------------------------
  redis:
    image: redis:6
    container_name: redis_cache
    restart: always
    ports:
      - "6379:6379"                          # 本地可访问 Redis
    networks:
      - backend

  # -------------------------------
  # 🧭 可视化工具(Adminer 管理 PostgreSQL)
  # -------------------------------
  adminer:
    image: adminer
    container_name: db_admin_ui
    depends_on:
      - db
    ports:
      - "8080:8080"                          # 访问 http://localhost:8080 使用图形界面
    networks:
      - backend

# -------------------------------
# 持久化卷:数据库数据(可扩展更多)
# -------------------------------
volumes:
  db_data:

# -------------------------------
# 网络配置:隔离 + 通信通道
# -------------------------------
networks:
  frontend:
  backend:

Compose字段说明

字段 层级 分类 作用 示例 是否必填 推荐使用场景
version 顶级字段 基础结构 定义 Compose 文件的语法版本 '3.9' 所有 Compose 文件必需
services 顶级字段 核心结构 定义多个容器服务 services: web: 定义服务入口点
volumes (root) 顶级字段 数据卷声明 统一声明卷名用于挂载 volumes: 定义数据卷,如数据持久化
data-volume:
networks (root) 顶级字段 网络声明 统一声明网络名 networks: 多个服务互联时使用
my-network:
build 服务字段 构建镜像 使用 Dockerfile 构建镜像 build: . 需要自定义构建时使用,如修改代码、插件等
image 服务字段 使用镜像 指定使用的镜像 image: node:18 是(build 和 image 至少一个) 直接使用官方或已有镜像时
container_name 服务字段 容器命名 给容器指定名称 container_name: myapp 容器需指定名字便于识别、依赖或调试
ports 服务字段 网络映射 映射主机端口到容器端口 "3000:3000" 服务对外暴露 HTTP、API、端口等
volumes 服务字段 挂载数据 将主机目录挂载到容器 - ./data:/app/data 容器存本地缓存、数据卷、挂载需求时
environment 服务字段 环境变量 设置容器内的环境变量 - NODE_ENV=production 设置注入环境变量,如 NODE_ENV、密钥
depends_on 服务字段 依赖关系 设置容器启动顺序 depends_on: 确保按顺序、缓存先启动等场景
- db
command 服务字段 启动命令 覆盖镜像默认启动命令 command: ["npm", "start"] 更改默认启动命令
entrypoint 服务字段 启动命令 覆盖默认入口脚本 entrypoint: ["/start.sh"] 替换默认入口脚本
restart 服务字段 重启策略 定义容器失败后的重启行为 restart: always 服务异常重启自动重启
tty 服务字段 控制台 分配终端 tty: true 运行交互型容器,如终端工具
stdin_open 服务字段 控制台 保持标准输入打开 stdin_open: true 保持 stdin 打开,配合 tty 使用
extra_hosts 服务字段 网络配置 额外 DNS 映射 extra_hosts: 需要自定义 host 映射,如 host-gateway
- "host.docker.internal:host-gateway"
logging 服务字段 日志配置 配置容器日志驱动 logging: 服务大量日志需要管理时
driver: "json-file"
networks 服务字段 网络配置 指定容器所属网络 networks: 指定使用自定义网络名称
- my-network
healthcheck 服务字段 健康检查 容器运行健康检查 healthcheck: 对容器健康状态有监控要求
test: ["CMD", "curl", "-f", "http://localhost"]

为什么别人可以只用一条 docker run 命令就跑起来,而我们却要写 Dockerfile 和 docker-compose.yml?

🎯 一句话解释:

docker run 是直接使用别人构建好的镜像 来启动服务(快速试玩)
Dockerfile 和 docker-compose.yml 是自己构建镜像 / 管理服务配置时用的工具(长期运行服务,可定制化)

🐳 Docker 使用方式:三种典型模式总览

🚀 使用方式一:拉取官方镜像直接运行(最快速)

无需 Dockerfile,适合使用已有服务(如 Redis、Nginx、Verdaccio)

bash 复制代码
# 拉取镜像(可选,run 时会自动拉)
docker pull verdaccio/verdaccio:nightly-master

# 直接运行
docker run -it --rm --name verdaccio -p 4873:4873 verdaccio/verdaccio

✅ 适合:快速试用、已有服务、临时环境


🧱 使用方式二:自定义 Dockerfile 构建镜像再运行

适合自己项目,需要控制依赖、环境、命令

Dockerfile 复制代码
# Dockerfile 示例
FROM node:18
WORKDIR /app
COPY . .
RUN yarn install
CMD ["yarn", "dev"]
bash 复制代码
# 构建镜像
docker build -t my-app .

# 运行镜像
docker run -p 3000:3000 my-app

✅ 适合:Web 项目、自研服务、定制部署


📦 使用方式三:使用 Docker Compose 管理多个服务

适合项目多服务(前端+后端+数据库)、开发部署协同

yaml 复制代码
# docker-compose.yml
version: "3.9"
services:
  frontend:
    build: .
    ports:
      - "3000:3000"
  backend:
    image: my-backend
    ports:
      - "5000:5000"
bash 复制代码
# 一键构建并启动
docker compose up -d

✅ 适合:开发团队、微服务、多环境管理


🧠 总结对比

模式 是否需要 Dockerfile 是否自定义镜像 是否适合多服务 场景推荐
拉取镜像 + 运行 ❌ 否 ❌ 否 ❌ 否 快速启动已有服务
构建镜像 + 运行 ✅ 是 ✅ 是 ❌ 否 项目开发、部署
Compose 协同 可选 ✅ 支持 ✅ 是 团队协作、集成部署

✅ 推荐路径:先学 run → 再学 Dockerfile → 最后学 Compose

🔥 Docker 热更新 vs 镜像构建:开发流程对比

🎯 对比目的

帮助你理解在本地开发时,代码修改是否会自动反映到容器中,应该使用哪种方式更合适。

🧪 热更新模式(推荐开发)

使用 volumes 挂载本地代码,代码改动后容器实时生效(无需重启)

✅ 特点
项目 内容
是否需要构建镜像 ❌ 不需要
是否实时反映代码改动 ✅ 是
适合场景 本地开发、调试
启动方式 docker run -v $(pwd):/app or docker-compose.dev.yml
是否依赖 Dockerfile ❌ 可选
优点 快速开发、热更新
缺点 稍微依赖本地环境一致性

📦 镜像构建模式(推荐部署)

每次改动后都重新 docker build 构建镜像,改动后不会自动生效

✅ 特点
项目 内容
是否需要构建镜像 ✅ 是
是否实时反映代码改动 ❌ 否(需重构建)
适合场景 发布、线上部署
启动方式 docker build && docker run
是否依赖 Dockerfile ✅ 是
优点 环境一致、可部署
缺点 每次都要重构建

🧠 什么时候该选哪个?

场景 推荐方式
本地开发 + 实时改动 ✅ 热更新(挂载代码)
正式打包 + 发布 ✅ 构建镜像
CI/CD 自动部署 ✅ 构建镜像推送 registry
临时测试官方服务 ✅ 拉取镜像 docker run

✅ 推荐写法示例(Compose)

热更新版 Compose
yaml 复制代码
services:
  app:
    image: node:18
    volumes:
      - ./my-app:/app
      - /app/node_modules
    working_dir: /app
    command: yarn dev
    ports:
      - "3000:3000"

构建部署版 Compose
yaml 复制代码
services:
  app:
    build: .
    ports:
      - "3000:3000"

📁 数据持久化与挂载路径

🧠 什么是持久化?

在 Docker 中,如果你不做任何挂载,容器里的数据是临时的,一旦容器被删除,数据就全部消失了(比如数据库记录、上传的文件、缓存等)。

为了让数据保存到你本地的硬盘上 ,我们就要使用 Docker 的 volumesbind mount持久化挂载


🔁 为什么数据库特别需要持久化挂载?

因为数据库运行时会产生大量的数据文件,如果你不挂载出来,一旦重启容器或删除,数据库就像「格式化」了一样,什么都没了 😱


✅ 持久化挂载语法说明:

yaml 复制代码
volumes:
  - 本地路径:容器路径
📦 各大数据库默认挂载路径对照表
数据库 容器内挂载路径(必须) 示例挂载配置
PostgreSQL /var/lib/postgresql/data ./data/postgres:/var/lib/postgresql/data
MySQL / MariaDB /var/lib/mysql ./data/mysql:/var/lib/mysql
MongoDB /data/db ./data/mongo:/data/db
Redis /data ./data/redis:/data
Elasticsearch /usr/share/elasticsearch/data ./data/es:/usr/share/elasticsearch/data

🐳 多数据库服务 Compose 配置(带本地挂载 + 注释)

yaml 复制代码
version: '3.9'

services:
  # -------------------------------
  # PostgreSQL 数据库
  # -------------------------------
  postgres:
    image: postgres:14
    container_name: postgres_db
    restart: always
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: appdb
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    networks:
      - backend

  # -------------------------------
  # MySQL 数据库
  # -------------------------------
  mysql:
    image: mysql:8
    container_name: mysql_db
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: appdb
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    volumes:
      - ./data/mysql:/var/lib/mysql
    ports:
      - "3306:3306"
    networks:
      - backend

  # -------------------------------
  # MongoDB 数据库
  # -------------------------------
  mongo:
    image: mongo:5
    container_name: mongo_db
    restart: always
    volumes:
      - ./data/mongo:/data/db
    ports:
      - "27017:27017"
    networks:
      - backend

# -------------------------------
# 网络配置
# -------------------------------
networks:
  backend:

❓ 常见问题解答(FAQ)

📚 FAQ:初次使用 Docker 启动镜像失败,如何通过配置镜像加速解决?

🔍 问题表现:

• docker pull 卡住很久

• 报错 TLS handshake timeout / connection refused

• docker run 无法正常启动容器 ✅ 原因分析:

Docker 默认从国外 Docker Hub 拉取镜像,国内网络不稳定或被墙,导致拉取失败

✅ 解决方案:配置国内镜像源 在 ~/.docker/daemon.json 中添加:

json 复制代码
{
  "builder": {
    "gc": {
      "defaultKeepStorage": "20GB",
      "enabled": true
    }
  },
  "experimental": false,
  "registry-mirrors": [
    "https://registry.docker-cn.com",
    "https://mirror.baidubce.com",
    "https://hub-mirror.c.163.com"
  ]
}

然后重启 Docker Desktop,使配置生效。

✅ 推荐国内镜像源列表

镜像源 地址
Docker 中国官方 registry.docker-cn.com
百度云加速 mirror.baidubce.com
网易云加速 hub-mirror.c.163.com
阿里云加速(登录后获取) cr.console.aliyun.com/cn-hangzhou...

📚 FAQ:使用 .env 后 Docker Compose 启动失败的常见原因与解决方案

❓Q1:为什么不用 .env 的时候服务可以正常运行,一用就出错?

原因 说明 解决方案
✅ 变量未成功加载 .env 文件未传入或位置不对 使用 --env-file .env 显式指定
⚠️ 变量名拼写错误 Compose 中写了 ${WEB_PATH},但 .env 里没定义或拼错 对齐变量名,一字不差
⚠️ 中文路径、空格未加引号 .env 中的路径包含中文或空格 .env 中加引号:WEB_PATH="/Users/project/..."
⚠️ registry/npm 源访问失败 使用 npm/yarn 默认源被墙 配置淘宝镜像:yarn config set registry registry.npmmirror.com
⚠️ DNS 解析失败 使用 Compose 创建了隔离网络,无法访问公网 添加 dns: 字段(如 8.8.8.8)解决域名解析问题

❓Q2:为啥用 .env 后需要多写这么多配置(DNS、registry 等)?

.env 提供的是"变量抽象",但实际运行的路径、网络、镜像仍然需要你手动保证正确。

所以额外配置是为了弥补:

• 网络隔离带来的 DNS 问题

• 源地址无法访问导致的安装失败

• 字符编码或路径解析错误

✅ 这些内容可以一次性写好,并复用于多个服务/项目。

❓Q3:哪些字段建议抽离为 .env 变量?

字段 是否推荐使用变量 解决方案
container_name ✅ 推荐 多服务命名统一好管理
volumes(本地路径) ✅ 推荐 本地路径变化多,建议抽离
ports ✅ 推荐 避免端口冲突
environment ✅ 推荐 支持多环境切换(dev/prod)
command ✅ 推荐 如果启动命令复杂可抽离

📌 建议写法小结 ✅ .env 示例(记得加引号)

env 复制代码
WEB_PATH="/Users/project/[项目名称]"
WEB_PORT=8813
WEB_NAME=web_portal_dev
NODE_ENV=development

✅ docker-compose.yml 示例

yaml 复制代码
volumes:
  - ${WEB_PATH}:/app
ports:
  - "${WEB_PORT}:${WEB_PORT}"
container_name: ${WEB_NAME}
dns:
  - 8.8.8.8
command: sh -c "yarn config set registry https://registry.npmmirror.com && yarn install && yarn dev"
相关推荐
用户87612829073741 分钟前
前端ai对话框架semi-design-vue
前端·人工智能
雷渊3 分钟前
深入分析mybatis中#{}和${}的区别
java·后端·面试
干就完了14 分钟前
项目中遇到浏览器跨域前端和后端解决方案以及大概过程
前端
我是福福大王6 分钟前
前后端SM2加密交互问题解析与解决方案
前端·后端
实习生小黄10 分钟前
echarts 实现环形渐变
前端·echarts
_未知_开摆17 分钟前
uniapp APP端在线升级(简版)
开发语言·前端·javascript·vue.js·uni-app
sen_shan29 分钟前
Vue3+Vite+TypeScript+Element Plus开发-02.Element Plus安装与配置
前端·javascript·typescript·vue3·element·element plus
老友@41 分钟前
Kafka 全面解析
服务器·分布式·后端·kafka
疾风铸境41 分钟前
Qt5.14.2+mingw64编译OpenCV3.4.14一次成功记录
前端·webpack·node.js
Java中文社群43 分钟前
超实用!Prompt程序员使用指南,大模型各角色代码实战案例分享
后端·aigc