Docker 容器化迁移实战指南
记录使用 Docker 容器化技术迁移 Python 项目(针对无常驻后台服务)的完整流程,包括镜像构建、推送到腾讯云镜像仓库、新服务器拉取运行,脚本项目隐私数据进行挂载卷的处理并附带完整交互过程和终端输出。
Docker 容器化迁移实战指南
以前迁移项目要打包代码、装依赖、配环境,费时费力。现在用 Docker 一次构建、到处运行,省心多了,附上完整记录
一、场景说明
- 迁移项目:和平营地多账号自动激活工具(Python 脚本)
- 项目特点:不是常驻服务,是定时执行的一次性脚本
- 迁移方式:构建 Docker 镜像 → 推送到腾讯云镜像仓库 → 新服务器拉取运行
- 学习目标:掌握容器化迁移的标准流程
二、环境信息
| 项目 | 旧服务器 | 新服务器 |
|---|---|---|
| IP | 192.0.2.100 | 192.0.2.200 |
| 系统 | Ubuntu 22.04 | Ubuntu 22.04 |
| SSH 端口 | 22 | 2894 |
| 项目路径 | /home/ubuntu/UserubuntuScripts/campus_activator | /home/ubuntu/ |
| Python 版本 | 3.10.12 | 3.10.x |
| 镜像仓库 | 腾讯云 TCR | 腾讯云 TCR |
三、迁移流程概览
旧服务器 腾讯云镜像仓库 新服务器
│ │ │
│ 1. 创建 Dockerfile │ │
│ 2. 构建镜像 │ │
│ 3. 登录仓库 │ │
│ 4. 推送镜像 ─────────────────────►│ │
│ │ 5. 镜像存储 │
│ │ │
│ │◄──── 6. 拉取镜像 ────────────│
│ │ │
│ 7. 手动传输配置文件 ─────────────────────────────────────────────►│
│ │ │
│ │ 8. 配置 cron 定时执行 │
四、详细步骤
第一步:创建 Dockerfile
操作位置: 旧服务器
为什么要写 Dockerfile?
Dockerfile 告诉 Docker 如何构建镜像:用什么基础环境、安装什么依赖、复制什么代码、启动什么命令。
执行命令:
cd /home/ubuntu/UserubuntuScripts/campus_activator
cat > Dockerfile << 'EOF'
FROM python:3.10-slim
# 设置工作目录
WORKDIR /app
# 复制依赖文件并安装
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
# 复制项目代码
COPY . .
# 设置时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 启动命令
CMD ["python", "main.py"]
EOF
逐行解释:
| 指令 | 作用 |
|---|---|
FROM python:3.10-slim |
使用 Python 3.10 精简版作为基础镜像 |
WORKDIR /app |
设置工作目录为 /app |
COPY requirements.txt . |
复制依赖文件到容器 |
RUN pip install ... |
安装依赖(使用清华镜像源加速) |
COPY . . |
复制项目所有代码到容器 |
ENV TZ=Asia/Shanghai |
设置时区为中国上海 |
CMD ["python", "main.py"] |
容器启动时执行的命令 |
第二步:创建 .dockerignore
为什么要创建?
排除不需要的文件,减小镜像体积,避免敏感信息泄露。
cat > .dockerignore << 'EOF'
__pycache__
*.pyc
.git
.env
activation_history.json
*.log
EOF
执行结果:
ubuntu@server:~$ cat .dockerignore
__pycache__
*.pyc
.git
.env
activation_history.json
*.log
第三步:构建 Docker 镜像
操作位置: 旧服务器
执行命令:
docker build -t campus-activator:v1.0 .
执行结果:
ubuntu@server:~/UserubuntuScripts/campus_activator$ docker build -t campus-activator:v1.0 .
[+] Building 12.8s (11/11) FINISHED
=> [internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 435B 0.0s
=> [internal] load metadata for docker.io/library/python:3.10-slim 1.7s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 98B 0.0s
=> [1/6] FROM docker.io/library/python:3.10-slim@sha256:e5300dc020a26a34a 1.9s
=> [2/6] WORKDIR /app 0.2s
=> [3/6] COPY requirements.txt . 0.1s
=> [4/6] RUN pip install --no-cache-dir -r requirements.txt -i https://py 7.0s
=> [5/6] COPY . . 0.1s
=> [6/6] RUN ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && 0.2s
=> exporting to image 1.3s
=> => naming to docker.io/library/campus-activator:v1.0 0.0s
关键输出:
FINISHED- 构建成功naming to docker.io/library/campus-activator:v1.0- 镜像命名成功
查看构建结果:
ubuntu@server:~$ docker images | grep campus
campus-activator v1.0 c818082a2364 10 seconds ago 135MB
第四步:登录镜像仓库
操作位置: 旧服务器
为什么要登录? 镜像仓库需要认证才能推送镜像,防止未授权上传。
执行命令:
docker login --username=<腾讯云账号ID> ccr.ccs.tencentyun.com
执行结果:
ubuntu@server:~$ docker login ccr.ccs.tencentyun.com --username=100049281763
Password:
WARNING! Your credentials are stored unencrypted in '/home/ubuntu/.docker/config.json'.
Login Succeeded
注意事项:
username是腾讯云账号ID(数字),不是用户名- 密码在腾讯云 TCR 仓库的"访问凭证"里生成
- 登录凭证会保存在
~/.docker/config.json,后续推送无需重复登录
第五步:给镜像打 Tag 并推送
操作位置: 旧服务器
为什么要打 Tag? Tag 用于标识镜像版本,方便管理和追踪。
执行命令:
# 给镜像打 tag(格式:仓库地址/命名空间/镜像名:版本)
docker tag campus-activator:v1.0 ccr.ccs.tencentyun.com/campus-activator/campus-activator:v1.0
# 推送镜像
docker push ccr.ccs.tencentyun.com/campus-activator/campus-activator:v1.0
执行结果:
ubuntu@server:~/UserubuntuScripts/campus_activator$ docker push ccr.ccs.tencentyun.com/campus-activator/campus-activator:v1.0
The push refers to repository [ccr.ccs.tencentyun.com/campus-activator/campus-activator]
2dd5fef94311: Pushed
1bbc0535f33b: Pushed
8202e966040c: Pushed
4aac43874c8c: Pushed
a6d746f67f20: Pushed
782a216362de: Pushed
e95a6c7ea7d4: Pushed
35d37bb98412: Pushed
761b235e9780: Pushed
a38bf36a9525: Pushed
v1.0: digest: sha256:c818082a23646daf337a86ef4c5e2a293fa7f5d9f7a02a5f00cc39855c70e025 size: 856
关键输出:
- 每个
Pushed表示一个镜像层推送成功 digest: sha256:...是镜像的唯一标识
第六步:在新服务器拉取镜像
操作位置: 新服务器
执行命令:
# 先登录仓库
docker login --username=<腾讯云账号ID> ccr.ccs.tencentyun.com
# 拉取镜像
docker pull ccr.ccs.tencentyun.com/campus-activator/campus-activator:v1.0
执行结果:
ubuntu@new-server:~$ docker pull ccr.ccs.tencentyun.com/campus-activator/campus-activator:v1.0
v1.0: Pulling from campus-activator/campus-activator
a6d746f67f20: Pull complete
1bbc0535f33b: Pull complete
2dd5fef94311: Pull complete
782a216362de: Pull complete
761b235e9780: Pull complete
e95a6c7ea7d4: Pull complete
35d37bb98412: Pull complete
8202e966040c: Pull complete
4aac43874c8c: Pull complete
a38bf36a9525: Download complete
Digest: sha256:c818082a23646daf337a86ef4c5e2a293fa7f5d9f7a02a5f00cc39855c70e025
Status: Downloaded newer image for ccr.ccs.tencentyun.com/campus-activator/campus-activator:v1.0
第七步:传输配置文件
为什么要手动传输?
敏感配置(密码、Token)不应该放在镜像里,需要单独传输并挂载到容器。
执行命令:
# 在新服务器创建配置目录
mkdir -p /home/ubuntu/config
# 手动上传配置文件(通过 SCP 或其他方式)
# 配置文件包括:
# - config.json(账号配置)
# - .env(敏感信息)
# - activation_history.json(历史记录)
验证配置:
ubuntu@new-server:~$ ls -la /home/ubuntu/config/
-rw-rw-r-- 1 ubuntu ubuntu 2345 Jul 9 00:01 .env
-rw-rw-r-- 1 ubuntu ubuntu 70058 Jul 9 00:01 activation_history.json
-rw-rw-r-- 1 ubuntu ubuntu 7035 Jul 9 00:01 config.json
第八步:配置定时任务
为什么用 cron?
这个项目是一次性脚本,不需要常驻后台,用 cron 定时触发执行。
创建执行脚本:
cat > /home/ubuntu/run_activator.sh << 'EOF'
#!/bin/bash
docker run --rm -v /home/ubuntu/config:/app/config ccr.ccs.tencentyun.com/campus-activator/campus-activator:v1.0 >> /home/ubuntu/login.log 2>&1
EOF
chmod +x /home/ubuntu/run_activator.sh
配置 cron:
(crontab -l 2>/dev/null; echo "01 00 * * * /home/ubuntu/run_activator.sh") | crontab -
验证配置:
ubuntu@new-server:~$ crontab -l
01 00 * * * /home/ubuntu/run_activator.sh
说明:
01 00 * * *- 每天 00:01 执行--rm- 容器执行完自动删除-v /home/ubuntu/config:/app/config- 挂载配置目录
五、关键概念
Dockerfile 指令速查
| 指令 | 作用 | 示例 |
|---|---|---|
| FROM | 指定基础镜像 | FROM python:3.10-slim |
| WORKDIR | 设置工作目录 | WORKDIR /app |
| COPY | 复制文件到镜像 | COPY . . |
| RUN | 执行命令 | RUN pip install -r requirements.txt |
| ENV | 设置环境变量 | ENV TZ=Asia/Shanghai |
| CMD | 容器启动命令 | CMD ["python", "main.py"] |
常用 Docker 命令
# 构建镜像
docker build -t 镜像名:版本 .
# 查看本地镜像
docker images
# 推送镜像
docker push 仓库地址/镜像名:版本
# 拉取镜像
docker pull 仓库地址/镜像名:版本
# 运行容器(一次性)
docker run --rm 镜像名
# 运行容器(常驻后台)
docker run -d --name 容器名 镜像名
# 查看运行中的容器
docker ps
# 查看所有容器(包括已停止)
docker ps -a
# 删除容器
docker rm 容器名
# 删除镜像
docker rmi 镜像名
.dockerignore 常用规则
__pycache__ # Python 缓存
*.pyc # 编译文件
.git # Git 仓库
.env # 环境变量(敏感信息)
*.log # 日志文件
node_modules # Node.js 依赖
六、常见问题
问题1:Docker Hub 登录超时
错误: net/http: request canceled while waiting for connection
原因: 国内网络访问 Docker Hub 不稳定
解决: 使用国内镜像仓库(腾讯云 TCR、阿里云 ACR)
问题2:Dockerfile 语法错误
错误: invalid reference format
原因: 命令换行或特殊字符导致解析失败
解决: 把多行命令写成脚本文件执行
问题3:镜像推送到仓库失败
错误: unauthorized: authentication required
原因: 未登录或登录凭证过期
解决: 重新执行 docker login
问题4:容器执行完立即退出
这不是错误! 一次性脚本执行完就会退出,用 docker ps -a 查看历史记录。
七、经验总结
1. 镜像构建最佳实践
- 使用精简基础镜像:
python:3.10-slim比python:3.10小很多 - 合理利用缓存:先复制 requirements.txt 安装依赖,再复制代码
- 使用 .dockerignore:排除缓存和敏感文件
- 使用国内镜像源:pip 安装时加
-i https://pypi.tuna.tsinghua.edu.cn/simple
2. 配置文件安全
- 敏感信息不放镜像:密码、Token 放在 .env 文件,运行时挂载
- 配置文件单独传输:不要打包到镜像里
- 使用 volume 挂载:
-v /宿主机路径:/容器路径
3. 定时任务选择
- 一次性脚本:用 cron +
docker run --rm - 常驻服务:用
docker run -d+--restart unless-stopped - 复杂编排:用 docker-compose
4. 镜像仓库选择
- Docker Hub:国际通用,国内访问慢
- 腾讯云 TCR:国内快,免费额度够用
- 阿里云 ACR:国内快,和阿里云服务集成好
八、容器内交互命令
场景说明
项目不是常驻后台,但有时需要手动执行一些命令:
- 验证配置是否正确
- 指定运行某个账号
- 查看历史记录
- 调试排错
docker run 常用参数详解
| 参数 | 作用 | 示例 |
|---|---|---|
--rm |
容器退出后自动删除(适合一次性任务) | docker run --rm ... |
-it |
交互模式 + 伪终端(可以输入命令) | docker run -it ... |
-d |
后台运行(容器会常驻) | docker run -d ... |
--name |
给容器起名字(方便管理) | docker run --name myapp ... |
-v |
挂载目录(宿主机:容器) | -v /home/config:/app/config |
-p |
端口映射(宿主机:容器) | -p 8080:80 |
--restart |
重启策略 | --restart unless-stopped |
--entrypoint |
覆盖启动命令 | --entrypoint /bin/bash |
参数组合说明:
-it=-i(interactive,保持标准输入打开)+-t(tty,分配伪终端)- 不加
-it就无法交互输入命令 --rm和-d不要同时用(一个是一次性,一个是常驻)
方式一:封装管理脚本(推荐)
创建管理脚本:
cat > /home/ubuntu/campus.sh << 'EOF'
#!/bin/bash
IMAGE="ccr.ccs.tencentyun.com/campus-activator/campus-activator:v1.0"
CONFIG="/home/ubuntu/config"
case "$1" in
run)
docker run --rm -v $CONFIG:/app/config $IMAGE python main.py
;;
run-all)
docker run --rm -v $CONFIG:/app/config $IMAGE python main.py -r "$2"
;;
list)
docker run --rm -v $CONFIG:/app/config $IMAGE python main.py -l
;;
check)
docker run --rm -v $CONFIG:/app/config $IMAGE python main.py -V
;;
history)
docker run --rm -v $CONFIG:/app/config $IMAGE python main.py -H ${2:-20}
;;
shell)
docker run --rm -it -v $CONFIG:/app/config --entrypoint /bin/bash $IMAGE
;;
*)
echo "用法: campus.sh {run|run-all|list|check|history|shell}"
;;
esac
EOF
chmod +x /home/ubuntu/campus.sh
使用方式:
# 验证配置
./campus.sh check
# 查看账号列表
./campus.sh list
# 运行所有账号
./campus.sh run
# 指定运行某个账号
./campus.sh run-all "QQ大号"
# 查看最近20条记录
./campus.sh history
# 进入容器交互
./campus.sh shell
方式二:直接 docker run 命令
验证配置:
docker run --rm -v /home/ubuntu/config:/app/config \
ccr.ccs.tencentyun.com/campus-activator/campus-activator:v1.0 \
python main.py -V
参数拆解:
docker run- 运行容器--rm- 执行完自动删除容器-v /home/ubuntu/config:/app/config- 把宿主机的配置目录挂载到容器的 /app/configccr.ccs.tencentyun.com/...- 镜像地址python main.py -V- 覆盖默认启动命令,执行验证
运行指定账号:
docker run --rm -v /home/ubuntu/config:/app/config \
ccr.ccs.tencentyun.com/campus-activator/campus-activator:v1.0 \
python main.py -r "QQ大号"
进入容器交互:
docker run --rm -it -v /home/ubuntu/config:/app/config \
--entrypoint /bin/bash \
ccr.ccs.tencentyun.com/campus-activator/campus-activator:v1.0
参数拆解:
-it- 交互模式(可以输入命令)--entrypoint /bin/bash- 覆盖默认启动命令,直接进入 bash
方式三:docker exec 进入已运行容器
适合需要长时间调试的场景:
# 启动一个临时容器(不退出)
docker run -d --rm -it -v /home/ubuntu/config:/app/config \
--name campus-tools \
ccr.ccs.tencentyun.com/campus-activator/campus-activator:v1.0 \
sleep infinity
# 进入容器执行命令
docker exec -it campus-tools python main.py -V
docker exec -it campus-tools python main.py -l
docker exec -it campus-tools /bin/bash
# 调试完成后删除容器
docker stop campus-tools
参数说明:
sleep infinity- 让容器保持运行不退出docker exec -it- 进入已运行的容器docker stop- 停止容器
说明:文中 IP、账号信息均为教学演示虚拟地址
评论
暂无评论,来写第一条吧
