Docker 是现在后端开发、微服务、DevOps、云原生开发中非常常见的一项技术。

很多人在第一次接触 Docker 时,会觉得它就是“启动容器的工具”,然后开始背各种 docker run、docker ps、docker exec 命令。

但只记命令很难把 Docker 用明白。它要解决的问题是:

如何把应用程序和它所依赖的运行环境统一打包,让程序在不同机器上都能够以相同的方式运行。

比如一个 Python 项目在本地运行正常,但是部署到服务器以后可能出现:

1
2
3
4
5
6
Python 版本不同
系统依赖缺失
环境变量不同
数据库版本不同
Redis 没有安装
操作系统行为不同

最终就会出现经典问题:

1
在我电脑上明明可以运行。

Docker 的作用,就是尽可能减少这种环境差异。

下面从核心概念讲起,依次是镜像、容器、数据卷、网络、Dockerfile、Docker Compose,最后是真实项目中的用法。

一、先把 Docker 的核心概念搞清楚

学习 Docker 之前,先要理解几个概念:

1
2
3
4
5
6
Image
Container
Dockerfile
Volume
Network
Docker Compose

Docker 的日常使用基本都围绕它们展开。

Docker 和虚拟机有什么区别

传统虚拟机,比如 VMware 中安装一个 Ubuntu,大致结构是:

1
2
3
4
5
6
7
8
9
10
11
物理机
│
├── Windows
│
├── VMware
│
└── Ubuntu 虚拟机
├── Linux Kernel
├── Python
├── MySQL
└── Application

每个虚拟机都包含一套比较完整的操作系统。

Docker 则更接近:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
物理机
│
├── 操作系统
│
├── Docker Engine
│
├── Container A
│ ├── Python
│ └── Application
│
├── Container B
│ ├── Redis
│ └── Data
│
└── Container C
├── Nginx
└── Config

多个容器共享宿主机内核,因此 Docker 容器通常比传统虚拟机更加轻量。

可以简单理解为:

1
2
3
虚拟机:虚拟出一整台电脑

Docker:给应用创建一个相对独立的运行环境

Image 和 Container

其中最基础的是这两个:

1
2
Image
Container

Image 中文一般叫:

1
镜像

它可以理解成应用运行环境的模板。

例如:

1
2
3
4
5
6
7
nginx
redis
mysql
postgres
python
node
ubuntu

都可以作为 Docker 镜像存在。

比如:

1
docker pull nginx

表示下载 nginx 镜像。

查看本地镜像:

1
docker images

而 Container,也就是:

1
容器

可以理解成镜像运行以后产生的实例。

例如:

1
docker run nginx

整个过程可以理解成:

1
2
3
4
5
nginx Image
↓
docker run
↓
nginx Container

同一个镜像可以启动多个容器:

1
2
3
4
5
nginx Image
│
├── nginx-container-1
├── nginx-container-2
└── nginx-container-3

如果熟悉面向对象,也可以简单类比:

1
2
Image      ≈ Class
Container ≈ Object

当然这个类比并不完全严谨,但很适合初学阶段理解。

Dockerfile 和 Docker Compose

如果只是运行 nginx、Redis、MySQL,我们可以直接使用别人已经制作好的镜像。

但自己的项目怎么办?

比如:

1
2
3
4
5
FastAPI
Vue
Spring Boot
Node.js
Go

这时候就需要:

1
Dockerfile

Dockerfile 用来描述:

如何把自己的项目构建成 Docker 镜像。

例如:

1
2
3
4
5
6
7
8
9
10
11
使用 Python 3.12
↓
创建工作目录
↓
复制 requirements.txt
↓
安装依赖
↓
复制项目代码
↓
启动 FastAPI

这些步骤都可以写进 Dockerfile。

但是一个真实项目通常不只有一个容器。

例如:

1
2
3
4
5
6
7
8
9
Vue
+
FastAPI
+
PostgreSQL
+
Redis
+
Nginx

如果每个服务都单独写一条 docker run,管理起来会非常麻烦。

所以 Docker 又提供了:

1
Docker Compose

通过一个 compose.yaml 文件,就可以统一管理整个项目。

可以记住:

1
2
3
4
5
6
7
8
9
10
Dockerfile

解决:
一个镜像怎么构建


Docker Compose

解决:
多个容器怎么一起运行

二、Docker 的基本使用

安装好 Docker 后,可以先执行:

1
docker --version

查看 Docker 版本。

再执行:

1
docker compose version

检查 Docker Compose。

最后运行:

1
docker run hello-world

如果出现:

1
Hello from Docker!

说明 Docker 已经能够正常运行。

Windows 开发环境一般使用:

1
2
3
Docker Desktop
+
WSL 2

Ubuntu 或 Linux 服务器则通常直接安装 Docker Engine。

安装完成后,日常开发基本都围绕下面几个操作:

1
2
3
4
5
6
7
拉取镜像
创建容器
查看容器
停止容器
查看日志
进入容器
删除容器

镜像操作

下载 nginx:

1
docker pull nginx

指定标签(alpine 是基于 Alpine Linux 的精简版本):

1
docker pull nginx:alpine

查看镜像:

1
docker images

也可以写:

1
docker image ls

删除镜像:

1
docker rmi nginx

或者:

1
docker image rm nginx

Docker 镜像通常使用:

1
镜像名称:Tag

例如:

1
2
3
4
5
python:3.12
node:22
redis:7
postgres:17
nginx:alpine

如果不指定 Tag:

1
docker pull nginx

通常会使用:

1
nginx:latest

不过真实项目,尤其是生产环境,最好明确指定版本。

例如:

1
2
3
redis:7
postgres:17
python:3.12

而不是全部使用:

1
latest

否则某一天重新拉取镜像以后,实际版本可能发生变化。

创建和管理容器

运行 nginx:

1
docker run nginx

此时 nginx 会直接占用当前终端。

如果希望后台运行:

1
docker run -d nginx

其中:

1
-d

表示:

1
detach

也就是后台运行。

查看正在运行的容器:

1
docker ps

查看所有容器:

1
docker ps -a

给容器指定名称:

1
docker run -d --name my-nginx nginx

之后就可以直接使用容器名称进行操作。

停止:

1
docker stop my-nginx

重新启动:

1
docker start my-nginx

重启:

1
docker restart my-nginx

删除:

1
docker rm my-nginx

如果容器正在运行:

1
docker rm -f my-nginx

端口映射

Docker 容器内部有自己的网络空间。

即使 nginx 在容器内部监听:

1
80

宿主机也不能直接访问。

所以需要做端口映射。

例如:

1
2
3
4
docker run -d \
--name my-nginx \
-p 8080:80 \
nginx

这里:

1
8080:80

表示:

1
宿主机端口 : 容器端口

也就是:

1
2
3
4
5
6
7
8
9
localhost:8080
↓
宿主机 8080
↓
Docker
↓
容器 80
↓
nginx

此时浏览器访问:

1
http://localhost:8080

就可以访问 nginx。

其他服务也一样,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
FastAPI

8000:8000


MySQL

3306:3306


Redis

6379:6379

查看日志和进入容器

查看日志:

1
docker logs my-nginx

持续查看:

1
docker logs -f my-nginx

查看最后 100 行:

1
docker logs --tail 100 my-nginx

实际开发中,如果一个容器启动失败,第一件事通常就是:

1
docker logs 容器名

如果需要进入容器:

1
docker exec -it my-nginx bash

进入之后,就像操作普通 Linux 一样:

1
2
3
4
5
ls

pwd

cd /etc/nginx

退出:

1
exit

有些精简镜像没有 bash,这时候可以使用:

1
docker exec -it my-nginx sh

查看容器详细信息:

1
docker inspect my-nginx

查看容器资源占用:

1
docker stats

可以看到:

1
2
3
4
CPU
内存
网络
磁盘 IO

三、Docker 数据和网络

容器虽然很好用,但有两个问题必须解决:

1
2
3
数据保存在哪里?

不同容器怎么通信?

这两个问题分别对应:

1
2
Volume
Network

Volume:解决数据持久化

假设直接启动 PostgreSQL:

1
docker run postgres

官方 postgres 镜像声明了 VOLUME,不指定挂载时,数据库数据会写入 Docker 自动创建的匿名 Volume。

如果以后删除容器:

1
docker rm postgres

匿名 Volume 不会随容器一起删除(除非使用 docker rm -v),但它只有一串随机 ID,很难找到并在新容器中复用,数据实际上就等于丢了。

数据库显然不能这么用。

Docker 为此提供:

1
Volume

创建 Volume:

1
docker volume create postgres-data

查看:

1
docker volume ls

然后启动 PostgreSQL:

1
2
3
4
5
docker run -d \
--name postgres \
-e POSTGRES_PASSWORD=123456 \
-v postgres-data:/var/lib/postgresql/data \
postgres

关键部分:

1
-v postgres-data:/var/lib/postgresql/data

表示:

1
2
3
4
5
6
7
Docker Volume
postgres-data
↓
挂载
↓
Container
/var/lib/postgresql/data

这样数据库数据就不再完全依赖容器本身。

即使删除:

1
docker rm postgres

Volume 仍然存在。

重新创建 PostgreSQL,并挂载同一个 Volume,就可以继续读取之前的数据。

Bind Mount:把本地目录挂进容器

除了 Volume,还可以直接挂载宿主机目录。

例如:

1
2
3
4
docker run -d \
-p 8080:80 \
-v ./html:/usr/share/nginx/html \
nginx

这里:

1
./html

是宿主机目录。

1
/usr/share/nginx/html

是容器目录。

两者绑定以后:

1
2
3
宿主机修改文件
↓
容器立即看到变化

这种方式叫:

1
Bind Mount

开发环境中很常见。

一般可以这样选择:

1
2
3
4
5
6
7
8
数据库数据
→ Volume

项目源码
→ Bind Mount

配置文件
→ Bind Mount

Network:解决容器之间通信

假设现在有两个容器:

1
2
backend
postgres

那么 backend 怎么访问 postgres?

很多初学者第一反应是:

1
localhost:5432

但这是错误的。

因为:

1
容器里的 localhost

指的是:

1
容器自己

而不是宿主机,也不是另一个容器。

正确做法是创建一个 Docker 网络:

1
docker network create app-network

启动 PostgreSQL:

1
2
3
4
5
docker run -d \
--name postgres \
--network app-network \
-e POSTGRES_PASSWORD=123456 \
postgres

启动 backend:

1
2
3
4
docker run -d \
--name backend \
--network app-network \
backend-image

此时 backend 可以通过:

1
postgres:5432

访问数据库。

例如:

1
postgresql://postgres:123456@postgres:5432/app

这里:

1
postgres

就是容器名称。

Docker 网络会自动把容器名称解析成对应容器的地址。

以后遇到:

1
Connection refused

首先就要检查:

1
是不是把数据库地址错误写成 localhost 了?

四、Dockerfile:把自己的项目放进 Docker

假设有一个 FastAPI 项目:

1
2
3
4
5
6
7
8
docker-demo/
│
├── app/
│ └── main.py
│
├── requirements.txt
├── Dockerfile
└── .dockerignore

main.py:

1
2
3
4
5
6
7
8
9
10
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def root():
return {
"message": "Hello Docker"
}

requirements.txt:

1
2
fastapi
uvicorn[standard]

然后创建:

1
Dockerfile

内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
FROM python:3.12-slim

WORKDIR /app

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

这个 Dockerfile 已经包含了最常用的几个指令。

FROM、WORKDIR、COPY、RUN

首先:

1
FROM python:3.12-slim

表示当前镜像基于:

1
python:3.12-slim

构建。

然后:

1
WORKDIR /app

表示后面的命令都默认在:

1
/app

目录中执行。

类似:

1
cd /app

接下来:

1
COPY requirements.txt .

表示把宿主机中的:

1
requirements.txt

复制到镜像中的:

1
/app

再执行:

1
RUN pip install --no-cache-dir -r requirements.txt

安装 Python 依赖。

注意:

1
RUN

是在:

1
构建镜像阶段

执行的。

最后:

1
COPY . .

把项目代码复制进镜像。

EXPOSE 和 CMD

1
EXPOSE 8000

表示应用预计使用:

1
8000

端口。

但 EXPOSE 本身并不会自动把端口暴露给宿主机。

真正运行时仍然需要:

1
-p 8000:8000

最后:

1
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

表示容器启动时默认执行:

1
uvicorn

这里需要特别注意:

1
--host 0.0.0.0

如果使用:

1
127.0.0.1

程序可能只能在容器内部访问。

构建并运行镜像

构建:

1
docker build -t fastapi-demo .

这里:

1
-t fastapi-demo

表示给镜像命名。

最后的:

1
.

表示:

1
当前目录作为 Build Context

构建完成后查看:

1
docker images

然后启动:

1
2
3
4
docker run -d \
--name fastapi-demo \
-p 8000:8000 \
fastapi-demo

浏览器打开:

1
http://localhost:8000

应该能够看到:

1
2
3
{
"message": "Hello Docker"
}

FastAPI 文档:

1
http://localhost:8000/docs

这样就完成了一个最基本的项目 Docker 化。

Dockerfile 的缓存机制

Dockerfile 中指令的顺序会影响构建缓存。

例如不要简单写成:

1
2
3
COPY . .

RUN pip install -r requirements.txt

因为只要任何项目代码发生改变:

1
COPY . .

这一层缓存就会失效。

后面的依赖安装也可能重新执行。

更推荐:

1
2
3
4
5
COPY requirements.txt .

RUN pip install -r requirements.txt

COPY . .

因为依赖文件:

1
requirements.txt

通常变化频率远低于业务代码。

这样平时只修改:

1
main.py

Docker 就可以复用前面的依赖缓存。

构建速度会快很多。

.dockerignore

项目里还应该创建:

1
.dockerignore

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.git
.gitignore

.env

__pycache__
*.pyc

.venv
venv

node_modules

.idea
.vscode

dist
build

它的作用类似:

1
.gitignore

只是它控制的是:

哪些内容不要放进 Docker Build Context。

如果不写 .dockerignore,项目中的:

1
2
3
4
5
6
node_modules
.venv
.git
缓存
日志
大文件

都有可能一起发送给 Docker。

结果就是:

1
2
3
构建很慢
镜像变大
甚至可能泄露敏感文件

所以真实项目最好都配置 .dockerignore。

五、Docker Compose:管理完整项目

当一个项目开始出现:

1
2
3
4
backend
postgres
redis
frontend

继续使用大量 docker run 命令就不合适了。

这时候应该使用:

1
Docker Compose

假设我们有:

1
2
3
4
5
FastAPI
+
PostgreSQL
+
Redis

可以创建:

1
compose.yaml

内容如下:

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
services:

backend:
build: .
ports:
- "8000:8000"
environment:
DATABASE_URL: postgresql://postgres:123456@postgres:5432/app
REDIS_URL: redis://redis:6379/0
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_started

postgres:
image: postgres:17
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: "123456"
POSTGRES_DB: app
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d app"]
interval: 5s
timeout: 5s
retries: 5

redis:
image: redis:7

volumes:
postgres-data:

然后只需要:

1
docker compose up

就可以启动整个项目。

后台运行:

1
docker compose up -d

重新构建:

1
docker compose up -d --build

Compose 配置怎么理解

在:

1
services:

下面,每一个对象都可以理解成一个服务。

例如:

1
2
3
4
services:
backend:
postgres:
redis:

相当于三个容器服务。

build:

1
2
backend:
build: .

表示:

1
根据当前目录中的 Dockerfile 构建

image:

1
2
redis:
image: redis:7

表示:

1
直接使用 redis:7 镜像

端口:

1
2
ports:
- "8000:8000"

相当于:

1
docker run -p 8000:8000

环境变量:

1
2
environment:
DATABASE_URL: xxx

相当于:

1
-e DATABASE_URL=xxx

数据卷:

1
2
volumes:
- postgres-data:/var/lib/postgresql/data

用来持久化 PostgreSQL 数据。

Compose 的服务通信

Docker Compose 默认会给整个项目创建一个内部网络。

因此:

1
backend

可以直接访问:

1
2
postgres
redis

PostgreSQL:

1
postgres:5432

Redis:

1
redis:6379

所以:

1
DATABASE_URL

应该写:

1
postgresql://postgres:123456@postgres:5432/app

而不是:

1
postgresql://postgres:123456@localhost:5432/app

可以把服务名理解成 Compose 网络中的内部域名。

整体关系:

1
2
3
4
5
6
7
8
9
Browser
│
│ localhost:8000
↓
backend
│
├──────→ postgres:5432
│
└──────→ redis:6379

depends_on 和 healthcheck

很多人会写:

1
2
depends_on:
- postgres

但这只意味着:

1
2
先启动 postgres 容器
再启动 backend 容器

它不一定意味着:

1
PostgreSQL 已经真正完成初始化

所以数据库最好配合:

1
healthcheck:

例如:

1
2
3
4
5
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d app"]
interval: 5s
timeout: 5s
retries: 5

然后 backend:

1
2
3
depends_on:
postgres:
condition: service_healthy

这样整体启动过程就是:

1
2
3
4
5
6
7
启动 PostgreSQL
↓
执行 healthcheck
↓
数据库 healthy
↓
启动 backend

这样启动顺序会更可靠。

Compose 常用命令

启动:

1
docker compose up

后台启动:

1
docker compose up -d

重新构建:

1
docker compose up -d --build

查看服务:

1
docker compose ps

查看日志:

1
docker compose logs

实时查看:

1
docker compose logs -f

只看 backend:

1
docker compose logs -f backend

进入 backend:

1
docker compose exec backend bash

停止:

1
docker compose stop

重新启动:

1
docker compose start

删除容器和 Compose 网络:

1
docker compose down

如果执行:

1
docker compose down -v

还会删除 Volume。

所以数据库项目中一定要谨慎。

六、真实项目中的 Docker 使用方式

下面把前面的内容放进一个更接近真实的项目结构里。假设项目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
my-project/
│
├── frontend/
│ ├── src/
│ ├── package.json
│ └── Dockerfile
│
├── backend/
│ ├── app/
│ ├── requirements.txt
│ └── Dockerfile
│
├── compose.yaml
├── .env
└── README.md

整个系统:

1
2
3
4
5
6
7
Frontend
+
Backend
+
PostgreSQL
+
Redis

前端使用多阶段构建

Vue 或 React 项目适合使用:

1
Multi-stage Build

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
FROM node:22-alpine AS builder

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

RUN npm run build


FROM nginx:alpine

COPY --from=builder /app/dist /usr/share/nginx/html

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

第一阶段:

1
2
3
4
5
6
7
Node.js
↓
安装依赖
↓
编译项目
↓
得到 dist

第二阶段:

1
2
3
4
5
nginx
↓
复制 dist
↓
运行

最终生产镜像不需要:

1
2
3
Node.js
node_modules
项目源码

只需要:

1
2
3
nginx
+
dist

这样可以明显减小镜像体积。

使用环境变量

真实项目基本都需要:

1
2
3
4
DATABASE_URL
REDIS_URL
SECRET_KEY
API_KEY

Docker 可以通过:

1
-e

传入。

例如:

1
2
3
4
docker run \
-e APP_ENV=production \
-e DEBUG=false \
my-app

也可以通过 .env:

1
2
3
APP_ENV=production
DEBUG=false
DATABASE_URL=postgresql://postgres:123456@postgres:5432/app

然后:

1
docker run --env-file .env my-app

需要注意:

1
不要把真正的 Token、密码、API Key 直接写进 Dockerfile。

例如不建议:

1
ENV API_KEY=xxxxxx

因为 Docker 镜像可能被:

1
2
3
4
上传
共享
推送仓库
导出

敏感信息就可能泄露。

设置自动重启

服务器上的容器一般希望能够自动恢复。

可以:

1
2
3
docker run \
--restart unless-stopped \
my-app

Compose 中:

1
2
3
services:
backend:
restart: unless-stopped

常见策略:

1
2
3
4
no
always
on-failure
unless-stopped

生产环境中:

1
unless-stopped

是比较常见的选择。

限制 CPU 和内存

Docker 也可以限制容器资源。

例如:

1
2
3
4
docker run \
--memory="512m" \
--cpus="1.0" \
my-app

表示:

1
2
3
最大内存:512 MB

CPU:1 Core

这样可以防止某个容器因为:

1
2
3
内存泄漏
死循环
异常任务

耗尽整台服务器资源。

资源监控:

1
docker stats

七、Docker 常见问题和排错思路

实际使用中,报错大多集中在下面几类。

容器启动后立即退出

先查看:

1
docker ps -a

然后:

1
docker logs 容器名

常见原因:

1
2
3
4
5
6
启动命令错误
环境变量缺失
程序运行报错
数据库连接失败
配置文件错误
依赖没有安装

Docker 容器通常和它的主进程生命周期绑定。

也就是说:

1
2
3
主进程结束
↓
容器退出

所以:

1
Exited

本身并不一定是 Docker 的问题。

很多时候是容器里的应用退出了。

端口被占用

如果出现:

1
port is already allocated

说明宿主机端口已经被占用。

Windows:

1
netstat -ano | findstr :8000

Linux:

1
sudo lsof -i :8000

也可以换宿主机端口:

1
2
ports:
- "8001:8000"

此时访问:

1
localhost:8001

实际映射到:

1
container:8000

修改代码以后没有变化

如果 Dockerfile 中:

1
COPY . .

表示代码是在构建镜像时复制进去的。

所以修改代码后通常需要:

1
docker compose up -d --build

重新构建镜像。

开发环境如果想实现实时同步,可以使用:

1
Bind Mount

把源码目录挂进容器。

容器访问不了数据库

最常见错误之一:

1
localhost

写错。

如果数据库也是 Compose 服务:

1
postgres:

后端应该连接:

1
postgres:5432

而不是:

1
localhost:5432

因为:

1
2
3
Container 中的 localhost
=
Container 自己

Docker 占用磁盘越来越大

先查看:

1
docker system df

可能占空间的有:

1
2
3
4
Images
Containers
Volumes
Build Cache

清理停止容器:

1
docker container prune

清理无用镜像:

1
docker image prune

清理网络:

1
docker network prune

统一清理:

1
docker system prune

更加彻底:

1
docker system prune -a

但要特别注意:

1
Volume 不要随便删。

特别是:

1
docker volume prune

因为里面可能存着:

1
2
3
MySQL
PostgreSQL
Redis

的重要数据。

八、把整个 Docker 工作流串起来

一个项目 Docker 化的流程基本是:

1
2
3
4
5
6
7
8
9
10
11
项目源码
↓
编写 Dockerfile
↓
docker build
↓
生成 Image
↓
docker run
↓
生成 Container

如果项目包含多个服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
Frontend Dockerfile
+
Backend Dockerfile
+
PostgreSQL Image
+
Redis Image
↓
compose.yaml
↓
docker compose up
↓
整个系统启动

实际开发过程中通常就是:

1
git clone 项目地址

进入项目:

1
cd project

准备环境变量:

1
cp .env.example .env

修改 .env。

然后:

1
docker compose up -d --build

查看:

1
docker compose ps

如果有问题:

1
docker compose logs -f

停止:

1
docker compose down

传统部署可能需要:

1
2
3
4
5
6
7
8
安装 Python
安装 Node.js
安装 PostgreSQL
安装 Redis
安装系统依赖
配置版本
配置 PATH
配置服务

使用 Docker 后,服务器上的基础环境可以大幅简化成:

1
2
3
4
5
6
7
安装 Docker
↓
拉取代码
↓
准备环境变量
↓
docker compose up -d

九、常用 Docker 命令速查

镜像

1
2
3
4
5
6
7
docker pull nginx

docker images

docker build -t my-app .

docker rmi my-app

容器

1
2
3
4
5
6
7
8
9
10
11
12
13
docker run -d my-app

docker ps

docker ps -a

docker stop container

docker start container

docker restart container

docker rm container

端口

1
docker run -p 8000:8000 my-app

日志

1
2
3
docker logs container

docker logs -f container

进入容器

1
docker exec -it container bash

Volume

1
2
3
docker volume ls

docker volume create app-data

Network

1
2
3
docker network ls

docker network create app-network

Compose

1
2
3
4
5
6
7
8
9
10
11
docker compose up

docker compose up -d

docker compose up -d --build

docker compose ps

docker compose logs -f

docker compose down

磁盘管理

1
2
3
docker system df

docker system prune

总结

Docker 的核心是这几块:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Docker
│
├── Image
│ └── 应用运行环境模板
│
├── Container
│ └── 镜像运行后的实例
│
├── Dockerfile
│ └── 描述如何构建镜像
│
├── Volume
│ └── 保存持久化数据
│
├── Network
│ └── 解决容器之间通信
│
└── Docker Compose
└── 统一管理多个服务

从源码到运行的主线是:

1
2
3
4
5
6
7
源码
↓
Dockerfile
↓
Image
↓
Container

再加上:

1
2
3
4
5
6
7
Container
+
Volume
+
Network
+
Docker Compose

就能把多个服务组成一个完整的应用。

如果能够独立完成:

1
2
3
4
5
6
7
给后端写 Dockerfile
给前端写多阶段 Dockerfile
启动 PostgreSQL 和 Redis
配置 Volume
配置容器网络
编写 compose.yaml
排查容器日志

日常开发中的 Docker 用法基本就够了。

后续继续深入时,可以再学习:

1
2
3
4
5
6
7
Docker BuildKit
Multi-stage Build
镜像安全
私有镜像仓库
Docker Registry
CI/CD
Kubernetes

这些内容都建立在前面讲到的几个概念之上:

1
2
3
4
5
6
Image
Container
Dockerfile
Volume
Network
Docker Compose