记录第一次使用docker打包镜像的操作步骤以及问题解决
文章目录
- 一、需求背景
- 二、Docker安装
- 2.1 安装环境&步骤
- 2.2 遇到的问题
- 三、整理项目目录&编写 Dockerfile
- 3.1 整理项目目录
- 3.2 编写Dockerfile
- 四、构建镜像
- 4.1 构建镜像
- 4.2 遇到的问题
- 五、本地测试
- 六、导入&运行
- 七、其他问题
- 7.1 dockerfile中/app的理解
- 7.2 修改代码问题
一、需求背景
公司的服务器没有python环境,也没有外网,只有docker,为了将我的Python程序放到这台服务器上运行,现在要把我的程序和python环境,以及相关依赖打包成镜像,放到这台服务器的docker中运行。
二、Docker安装
2.1 安装环境&步骤
安装环境:Linux centos 7
安装步骤:
# 移除旧版本(若无可跳过)
sudo yum remove -y docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
# 安装工具并添加官方仓库
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 安装并启动 Docker
sudo yum install -y docker-ce docker-ce-cli containerd.io
sudo systemctl enable --now docker
docker --version
2.2 遇到的问题
如果按照上面的命令安装时,报如下错误:
Downloading packages: No Presto metadata available for docker-ce-stable docker-buildx-plugin-0.14.1-1. FAILED https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-buildx-plugin-0.14.1-1.el7.x86_64.rpm: [Errno 14] curl#35 - “TCP connection reset by peer” 正在尝试其它镜像。
Error downloading packages: docker-buildx-plugin-0.14.1-1.el7.x86_64: [Errno 256] No more mirrors to try. containerd.io-1.6.33-3.1.el7.x86_64: [Errno 256] No more mirrors to try.
问题原因:当前是访问 https://download.docker.com 被重置。CentOS 7 已经 EOL(停止维护),某些上游仓库可能会不稳定
解决办法:可以切到国内/第三方镜像源:
# 更换阿里云镜像源,替换 docker-ce.repo 内的域名
sudo sed -ri 's|https://download.docker.com|https://mirrors.aliyun.com/docker-ce|g' /etc/yum.repos.d/docker-ce.reposudo yum clean all
sudo yum makecache fast
sudo yum -y --setopt=ip_resolve=4 install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
三、整理项目目录&编写 Dockerfile
3.1 整理项目目录
要确保项目根目录里有requirements.txt文件,如果没有,先生成:
pip freeze > requirements.txt
3.2 编写Dockerfile
在 your-project/ 下新建 Dockerfile,内容示例:
# 使用官方Python运行时作为父镜像
FROM python:3.9-slim
# 防止生成 pyc 文件 & 输出缓存
ENV PYTHONDONTWRITEBYTECODE=1 \PYTHONUNBUFFERED=1 \PIP_NO_CACHE_DIR=1
# 设置工作目录在容器内
WORKDIR /app
# 将当前目录下的所有文件复制到容器的 /app 目录下
COPY . .
# 安装项目所需的依赖(使用清华源加速下载)
RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
# 在容器启动时运行你的程序
CMD ["python", "./main.py"]
另外,也可以加一个 .dockerignore文件(减少无关文件进入镜像,加速构建):
.git
__pycache__/
*.pyc
*.pyo
.venv/
venv/
.idea/
.vscode/
四、构建镜像
4.1 构建镜像
# 构建镜像
docker build -t myapp:1.0 .# 查看镜像是否存在
docker images | grep myapp
4.2 遇到的问题
当我在构建镜像时报错:
ERROR: failed to solve: python:3.11-slim: failed to resolve source metadata for docker.io/library/python:3.11-slim: failed to do request: Head “https://registry-1.docker.io/v2/library/python/manifests/3.11-slim”: dial tcp 182.50.139.56:443: connect: connection refused
问题原因:Docker 在尝试从 registry-1.docker.io 拉取 python:3.11-slim 时连接失败,因为默认 Docker 使用官方源,速度慢且容易被拒绝。
解决办法:手动换指定国内镜像源,修改Dockerfile文件后,重新构建
FROM docker.m.daocloud.io/library/python:3.11-slim
五、本地测试
运行容器:
# python命令
python main.py --date 2025-01-01
# 对应的docker命令
docker run --rm -it myapp:1.0 python main.py --date 2025-01-01
解释:
- –rm:容器退出后自动清理
- -it:交互模式,可以实时看到输出日志
- myapp:1.0:你刚刚构建的镜像名
- 后面这部分命令会覆盖 Dockerfile 里的 CMD,传入参数执行
六、导入&运行
# 在构建机导出镜像
docker save myapp:1.0 -o myapp_1.0.tar
# 拷贝到目标服务器(以scp方式为例)
scp myapp_1.0.tar user@server:/opt/
# 导入镜像
docker load -i /opt/myapp_1.0.tar
# 在目标服务器上运行
docker run --rm -it myapp:1.0 python main.py --date 2025-01-01
七、其他问题
7.1 dockerfile中/app的理解
问题:我的项目根目录为myproject,为什么复制代码全部都是复制到/app下面了?这样项目根目录是不是就是/app了?那如果我建第二个镜像,那我是不是要重新设置一个工作目录app1?
回答:
容器内的工作目录设为 /app,后续所有 COPY、RUN、CMD 等命令,都会相对于这个目录来执行。如果带上项目的根目录,那么容器里会多出一层目录 /app/myproject/,这意味着你以后运行代码的时候,路径都得写成 /app/myproject/…。 而通常的做法是:把容器里的根工作目录设置成项目根目录,比如 /app。 这样容器内部的目录结构会比较扁平,后续维护也方便。
如果你要第二个项目怎么办?通常是每个项目一个独立镜像,项目 A 用 /app 作为工作目录,项目 B 也用 /app 作为工作目录,因为它们是不同的镜像,互不干扰。
7.2 修改代码问题
- 代码修改后是不是要重新构建镜像?
要看你代码和环境怎么分层:
如果代码直接写死在镜像里(比如 COPY . /app),那么代码变了,确实需要重新构建镜像。
如果镜像里只包含运行环境,代码是挂载到容器里的(docker run -v /local/path:/app …),那你修改本地代码后不需要重构镜像,直接重新运行容器即可。
- 重新构建镜像是不是会重新安装一遍环境?
不完全是。Docker 的 分层缓存 可以帮你加速,构建流程分为几层:
1、下载 python:3.11-slim
2、设置工作目录
3、拷贝 requirements.txt 并安装依赖
4、拷贝代码 如果你 只修改了代码,那么只有最后一层 COPY . .会重新执行, pip install 这层会直接用缓存,不会重新安装。 所以,只要 Dockerfile写得合理,改代码后重构镜像速度并不会慢。
- 怎么提高开发效率?
方式 A:开发环境(推荐) 先构建一个 只包含环境 的镜像(Python + 依赖),比如叫 myenv:1.0
运行容器时用挂载代码目录的方式:
bash docker run --rm -it -v $(pwd):/app myenv:1.0 python main.py --date 2025-08-22
这样修改本地代码,容器里立刻生效,不需要重构镜像。
方式 B:生产环境 把代码一起打包进镜像,构建出一个“完整可运行”的镜像,方便部署。在上线前才重新构建一次