说实话,对于很多刚接触云原生或者后端开发的朋友来说,“Docker 部署”这几个字听着挺唬人的。网上教程一大堆,但往往是要么太理论,要么直接甩个命令,跑不起来也不知道怎么排查。
今天,笔者(站长)就带大家亲手走一遍完整的部署流程。我们会从一个最简单的静态网站开始,再到一个带数据库的后端应用,最后聊聊生产环境里那些必须要注意的“坑”。这篇文章不讲虚的,全是实操,保证你跟着敲完,能真正理解 Docker 是怎么帮我们把项目“打包带走”的。
一、准备工作:先把“工具箱”搭好
在开始之前,我们需要一台服务器。如果你只是本地玩,装个 Docker Desktop 也行。但既然要学部署,笔者建议直接买一台云服务器,毕竟真正的生产环境都是在云上的。
关于服务器选择: 国内的话,阿里云、腾讯云的新用户活动力度挺大,几十块一年就能搞一台 2核2G 的轻量服务器,跑 Docker 绰绰有余。如果你需要稳定的海外访问体验,可以考虑搬瓦工或者 Vultr。笔者个人比较推荐新手先用国内的轻量服务器,网络延迟低,遇到问题也好查中文资料。
拿到服务器后,连上 SSH,先更新一下系统,然后安装 Docker:
# CentOS / Rocky Linux
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
sudo systemctl enable docker
# Ubuntu / Debian
sudo apt update
sudo apt install docker.io
sudo systemctl start docker
sudo systemctl enable docker
装完后跑一下 docker version,看到客户端和服务端都有版本信息,就算成了。
二、第一次部署:把静态网站塞进容器
很多人第一次接触 Docker 都是部署一个静态页面。我们直接上手,用 Nginx 镜像来托管一个简单的 HTML 文件。
2.1 准备你的项目文件
在服务器上创建一个目录,比如 my-site,里面放一个 index.html:
mkdir my-site && cd my-site
echo '<h1>Hello, Docker! 站长带你飞</h1>' > index.html
2.2 编写 Dockerfile
在同一个目录下创建 Dockerfile,注意没有后缀名:
# 使用官方的 Nginx 镜像作为基础
FROM nginx:alpine
# 把当前目录下的 index.html 复制到 Nginx 的默认网站目录
COPY index.html /usr/share/nginx/html/index.html
# 暴露 80 端口
EXPOSE 80
这里用了 nginx:alpine,这个镜像非常小,只有 20 多 MB,拉取速度快,安全性也高。
2.3 构建并运行
# 构建镜像,名字叫 my-static-site,版本号 v1
docker build -t my-static-site:v1 .
# 运行容器,把宿主机的 8080 端口映射到容器的 80 端口
docker run -d -p 8080:80 --name my-site-container my-static-site:v1
现在打开浏览器,访问 http://你的服务器IP:8080,就能看到你写的那个标题了。如果看不到,检查一下云服务器的防火墙有没有开放 8080 端口。
三、进阶实战:部署一个带数据库的 Python Web 应用
静态页面太简单了,我们上点硬菜。假设我们有一个 Flask 应用,需要连接 MySQL 数据库。这时候就要用到 Docker Compose 了,它能帮我们一键启动多个容器,并让它们互相通信。
3.1 项目结构
my-flask-app/
├── app.py
├── requirements.txt
├── Dockerfile
└── docker-compose.yml
app.py 内容(一个简单的计数器 API):
from flask import Flask
import mysql.connector
import os
app = Flask(__name__)
db_host = os.environ.get('DB_HOST', 'localhost')
db_user = os.environ.get('DB_USER', 'root')
db_pass = os.environ.get('DB_PASS', 'password')
@app.route('/')
def index():
try:
conn = mysql.connector.connect(host=db_host, user=db_user, password=db_pass, database='test')
cursor = conn.cursor()
cursor.execute("SELECT COUNT(*) FROM visits")
count = cursor.fetchone()[0]
cursor.close()
conn.close()
return f'Hello! You are visitor number {count}'
except Exception as e:
return f'Error: {str(e)}'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
requirements.txt:
flask
mysql-connector-python
Dockerfile:
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]
3.2 编写 docker-compose.yml
这是最关键的一步,它定义了我们要启动的服务:
version: '3.8'
services:
web:
build: .
ports:
- "5000:5000"
environment:
DB_HOST: db
DB_USER: root
DB_PASS: example
depends_on:
- db
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: example
MYSQL_DATABASE: test
volumes:
- mysql_data:/var/lib/mysql
ports:
- "3306:3306"
volumes:
mysql_data:
注意看 environment 里的 DB_HOST: db,这里的 db 就是下面那个 MySQL 服务的名字。Docker Compose 会自动创建一个内部网络,让 web 容器通过服务名 db 就能访问到数据库容器。
volumes 挂载:我们把 MySQL 的数据目录挂载到了命名卷 mysql_data 上。这样即使容器被删了,数据库里的数据也不会丢。这是生产环境必须做的!
3.3 启动整个应用
# 在 docker-compose.yml 所在目录执行
docker-compose up -d
第一次启动会先构建 Flask 镜像,然后拉取 MySQL 镜像,最后启动两个容器。访问 http://你的IP:5000,应该能看到计数器的输出。
如果想查看日志:docker-compose logs -f。想停掉所有服务:docker-compose down。
四、生产环境必须注意的 5 个要点
本地跑通了不代表就能上线。笔者见过太多人把 Docker 部署到生产环境后出各种幺蛾子,这里总结几个关键点:
- 不要用 root 用户运行容器。 默认 Docker 容器内是 root 权限,这很危险。在 Dockerfile 里加上
RUN useradd -m myuser和USER myuser。 - 合理设置资源限制。 用
--memory="512m" --cpus="0.5"限制容器能使用的内存和 CPU,防止某个容器把服务器资源吃光。 - 日志管理。 容器日志会无限增长,一定要配置日志轮转。可以在
docker run时加--log-opt max-size=10m --log-opt max-file=3。 - 使用 .dockerignore 文件。 跟
.gitignore一样,把node_modules、__pycache__等不需要的文件排除掉,能大大加快构建速度。 - 镜像标签不要用 latest。 线上部署一定要指定明确的版本号,比如
v1.2.3,否则哪天更新了镜像,你的服务可能就莫名其妙挂了。
五、关于域名与 HTTPS 的快速提醒
如果你打算把服务暴露到公网,光有 IP 和端口是不够的。你需要一个域名,然后配置反向代理(比如 Nginx 或 Traefik)来转发请求。
笔者强烈建议使用正规的域名注册商,比如阿里云、腾讯云、Namesilo 等。域名不贵,但能给你的项目一个专业的入口。配置好 Nginx 后,用 Certbot 或者 acme.sh 申请免费的 Let’s Encrypt SSL 证书,实现 HTTPS 访问。
这一步虽然不直接属于 Docker 部署的范畴,但它是让你项目“真正上线”的最后一步,千万别省。
六、写在最后
Docker 部署其实没有想象中那么复杂。它的核心思想就是“一次构建,到处运行”。你只要把环境依赖、配置文件、启动命令都写进 Dockerfile 和 docker-compose.yml 里,以后不管换到哪台服务器,只要装个 Docker,敲同样的命令,就能一模一样地跑起来。
今天我们从静态页面到带数据库的应用,再到生产环境的注意事项,全部走了一遍。希望这份指南能帮你跨过 Docker 部署的门槛。如果你在实操中遇到了任何报错,大概率是网络问题或者端口冲突,沉下心看看日志,基本上都能找到答案。
动手试试吧,把你自己写的项目容器化,那种掌控感真的很棒。