Docker入门实战:用容器部署你的第一个Web应用

Docker 解决了什么问题

“在我电脑上能跑啊” —— 这句话是所有开发者的噩梦。Docker 的出现就是为了解决环境不一致的问题。

简单理解:Docker 把你的应用和它需要的所有依赖打包成一个”容器”,在任何装了 Docker 的机器上都能一模一样地运行。

安装 Docker

Ubuntu/Debian

1
2
3
4
5
6
7
8
9
# 一键安装脚本
curl -fsSL https://get.docker.com | sh

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

# 重新登录后验证
docker --version
docker run hello-world

配置镜像加速

国内拉镜像很慢,配置加速器:

1
2
3
4
5
6
7
8
9
10
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<EOF
{
"registry-mirrors": [
"https://mirror.ccs.tencentyun.com",
"https://docker.mirrors.ustc.edu.cn"
]
}
EOF
sudo systemctl restart docker

核心概念

概念 类比 说明
镜像 (Image) 安装包 只读模板,包含运行环境
容器 (Container) 运行中的程序 镜像的实例,可读写
Dockerfile 安装脚本 描述如何构建镜像
Volume 外接硬盘 持久化数据,容器删了数据还在

实战:部署一个 Node.js 应用

1. 写 Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
FROM node:20-alpine

WORKDIR /app

# 先复制 package.json,利用缓存
COPY package*.json ./
RUN npm ci --only=production

# 再复制源码
COPY . .

EXPOSE 3000
CMD ["node", "server.js"]

2. 构建镜像

1
docker build -t my-app:v1 .

3. 运行容器

1
2
3
4
5
docker run -d \
--name my-app \
-p 3000:3000 \
--restart unless-stopped \
my-app:v1

Docker Compose:管理多个容器

实际项目通常需要多个服务配合(应用 + 数据库 + 缓存)。用 docker-compose 一键管理:

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
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
depends_on:
- db
- redis
environment:
- DB_HOST=db
- REDIS_HOST=redis

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

redis:
image: redis:alpine

volumes:
db_data:

启动:

1
docker compose up -d

常用命令速查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 查看运行中的容器
docker ps

# 查看日志
docker logs -f 容器名

# 进入容器内部
docker exec -it 容器名 sh

# 停止并删除所有容器
docker compose down

# 清理无用镜像(释放磁盘)
docker system prune -a

踩坑记录

坑1:容器里的数据重启后丢失

一定要用 Volume 挂载数据目录。数据库、上传文件这些必须持久化。

坑2:容器之间网络不通

同一个 docker-compose 文件里的服务自动在同一网络,用服务名互相访问。跨 compose 文件需要手动创建网络。

坑3:镜像太大

用 alpine 基础镜像,多阶段构建,.dockerignore 排除 node_modules 等大目录。

总结

Docker 的学习曲线不陡,但收益很大。一旦习惯了容器化部署,你就再也不想回到手动装环境的时代了。建议从自己的小项目开始练手,慢慢把所有服务都容器化。