docker + 阿里云 arc docker 推送和部署
背景
docker + 阿里云 arc docker 推送和部署
项目结构
python-api-docker-example/
├── app.py
├── Dockerfile
└── requirements.txt
文件内容
app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')
requirements.txt
Flask==2.0.1
Dockerfile
# 使用官方 Python 运行时作为基础镜像
FROM python:3.9-slim
# 设置工作目录
WORKDIR /app
# 复制 requirements.txt 文件到工作目录
COPY requirements.txt .
# 安装依赖
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用代码到工作目录
COPY . .
# 暴露端口
EXPOSE 5000
# 运行应用
CMD ["python", "app.py"]
本地测试和构建步骤
进入项目目录:
cd python-api-docker-example
(可选) 在本地测试应用:
pip install -r requirements.txt python app.py
然后在浏览器中访问
http://localhost:5000
查看应用。使用 Docker Compose 构建和运行应用:
docker-compose up --build
这将根据
docker-compose.yml
文件构建镜像并启动服务。应用将在http://localhost:9100
上运行。
镜像名称管理
默认情况下,Docker Compose 会根据项目目录名称和服务名称自动生成镜像名称,这可能会导致镜像名称过长。例如,如果项目目录名为 python-api-docker-example
,服务名为 python-api-service
,则生成的镜像名称为 python-api-docker-example-python-api-service
。
为了简化镜像名称,可以在 docker-compose.yml
中为服务指定一个自定义的镜像名称。例如:
version: "3.8"
services:
python-api-service:
build: .
container_name: python-api-service
image: surest-python-api:latest # 自定义镜像名称
ports:
- "9100:9100"
volumes:
- .:/app
environment:
- FLASK_ENV=development
这样构建的镜像名称就会是 surest-python-api:latest
。
构建、打包和推送镜像
构建 Docker 镜像:
docker-compose build
查看本地镜像:
docker images
登录到阿里云 ACR:
docker login --username=<你的阿里云用户名> registry.cn-hangzhou.aliyuncs.com
给镜像打标签:
docker tag surest-python-api:latest registry.cn-hangzhou.aliyuncs.com/<你的命名空间>/<你的镜像名>:<标签>
推送镜像到阿里云 ACR:
docker push registry.cn-hangzhou.aliyuncs.com/<你的命名空间>/<你的镜像名>:<标签>
从阿里云 ACR 拉取和部署镜像
在目标机器上登录到阿里云 ACR:
docker login --username=<你的阿里云用户名> registry.cn-hangzhou.aliyuncs.com
拉取镜像:
docker pull registry.cn-hangzhou.aliyuncs.com/<你的命名空间>/<你的镜像名>:<标签>
验证镜像是否已拉取:
docker images
你会在输出列表中看到刚刚拉取的镜像。
运行容器:
docker run -d -p 9100:9100 --name python-api-service registry.cn-hangzhou.aliyuncs.com/<你的命名空间>/<你的镜像名>:<标签>
这将以后台模式运行容器,并将主机的 9100 端口映射到容器的 9100 端口。
- 验证部署:
你可以通过访问
http://<目标机器IP>:9100
来验证应用是否正常运行。
更新镜像和重新部署
当你更新了应用并推送了具有相同标签的新镜像时,请注意以下几点:
推送新镜像:
- 新的镜像会覆盖远程注册表中旧的镜像。
- 旧的镜像层如果不再被任何标签引用,可能会在一段时间后被注册表的垃圾回收机制清理掉。
拉取新镜像:
- 在目标机器上执行
docker pull
时,Docker 会检查远程注册表中的镜像摘要(digest)是否与本地缓存的镜像摘要一致。 - 如果不一致,Docker 会拉取新的镜像层并更新本地镜像。
- 如果一致,Docker 会使用本地缓存的镜像,不会重新下载。
- 在目标机器上执行
重新部署容器:
- 如果你已经有一个同名的容器在运行,即使你拉取了新的镜像,正在运行的容器仍然使用的是旧的镜像。
- 你需要先停止并删除旧的容器,然后基于新拉取的镜像重新创建容器。
最佳实践:
- 为每次更新使用不同的标签,例如使用版本号(v1.0.0, v1.0.1 等)。
- 在部署脚本中加入健康检查,确保新容器启动成功后再停止旧容器。
latest
标签的特殊意义
latest
在 Docker 中有特殊的意义,需要特别注意:
默认标签:
- 当你在
docker pull
或docker run
命令中不指定标签时,Docker 会自动使用latest
标签。 - 例如:
docker pull nginx
等同于docker pull nginx:latest
。
- 当你在
约定俗成的含义:
latest
通常表示该镜像的最新稳定版本。- 它是 Docker 社区广泛接受的约定,用于标识最新的构建或发布版本。
自动更新行为:
- 当镜像仓库中的
latest
标签指向新的镜像时,下一次docker pull
会拉取新的镜像。 - 但这只在你显式执行
docker pull
时发生,已经运行的容器不会自动更新。
- 当镜像仓库中的
潜在问题:
- 版本不确定性:
latest
标签可能指向不同的镜像版本,这会导致环境之间的不一致性。 - 缓存问题:如果本地已经有
latest
镜像,Docker 可能不会自动拉取新的latest
镜像。 - 部署风险:在生产环境中使用
latest
标签可能会导致不可预测的行为。
- 版本不确定性:
使用建议:
- 开发环境:在开发环境中使用
latest
标签是可以接受的,因为它方便快速迭代和测试。 - 生产环境:在生产环境中,强烈建议使用明确的版本标签(如
v1.0.0
,v2.1.3
等)。 - CI/CD 流程:在自动化构建和部署流程中,建议使用版本化标签或 Git commit SHA 作为标签。
- 开发环境:在开发环境中使用
停止和删除容器
停止正在运行的容器:
docker stop python-api-service
删除已停止的容器:
docker rm python-api-service
或者,你可以使用一条命令同时停止并删除容器:
docker rm -f python-api-service
(可选) 删除镜像:
如果你不再需要该镜像,可以将其删除:
docker rmi registry.cn-hangzhou.aliyuncs.com/<你的命名空间>/<你的镜像名>:<标签>
本文由 邓尘锋 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Aug 27, 2025 at 10:44 am