docker + 阿里云 arc docker 推送和部署

in Docker with 0 comment

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"]

本地测试和构建步骤

  1. 进入项目目录:

    cd python-api-docker-example
  2. (可选) 在本地测试应用:

    pip install -r requirements.txt
    python app.py

    然后在浏览器中访问 http://localhost:5000 查看应用。

  3. 使用 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

构建、打包和推送镜像

  1. 构建 Docker 镜像:

    docker-compose build
  2. 查看本地镜像:

    docker images
  3. 登录到阿里云 ACR:

    docker login --username=<你的阿里云用户名> registry.cn-hangzhou.aliyuncs.com
  4. 给镜像打标签:

    docker tag surest-python-api:latest registry.cn-hangzhou.aliyuncs.com/<你的命名空间>/<你的镜像名>:<标签>
  5. 推送镜像到阿里云 ACR:

    docker push registry.cn-hangzhou.aliyuncs.com/<你的命名空间>/<你的镜像名>:<标签>

从阿里云 ACR 拉取和部署镜像

  1. 在目标机器上登录到阿里云 ACR:

    docker login --username=<你的阿里云用户名> registry.cn-hangzhou.aliyuncs.com
  2. 拉取镜像:

    docker pull registry.cn-hangzhou.aliyuncs.com/<你的命名空间>/<你的镜像名>:<标签>
  3. 验证镜像是否已拉取:

    docker images

    你会在输出列表中看到刚刚拉取的镜像。

  4. 运行容器:

    docker run -d -p 9100:9100 --name python-api-service registry.cn-hangzhou.aliyuncs.com/<你的命名空间>/<你的镜像名>:<标签>

    这将以后台模式运行容器,并将主机的 9100 端口映射到容器的 9100 端口。

  5. 验证部署:

    你可以通过访问 http://<目标机器IP>:9100 来验证应用是否正常运行。

更新镜像和重新部署

当你更新了应用并推送了具有相同标签的新镜像时,请注意以下几点:

  1. 推送新镜像

    • 新的镜像会覆盖远程注册表中旧的镜像。
    • 旧的镜像层如果不再被任何标签引用,可能会在一段时间后被注册表的垃圾回收机制清理掉。
  2. 拉取新镜像

    • 在目标机器上执行 docker pull 时,Docker 会检查远程注册表中的镜像摘要(digest)是否与本地缓存的镜像摘要一致。
    • 如果不一致,Docker 会拉取新的镜像层并更新本地镜像。
    • 如果一致,Docker 会使用本地缓存的镜像,不会重新下载。
  3. 重新部署容器

    • 如果你已经有一个同名的容器在运行,即使你拉取了新的镜像,正在运行的容器仍然使用的是旧的镜像。
    • 你需要先停止并删除旧的容器,然后基于新拉取的镜像重新创建容器。
  4. 最佳实践

    • 为每次更新使用不同的标签,例如使用版本号(v1.0.0, v1.0.1 等)。
    • 在部署脚本中加入健康检查,确保新容器启动成功后再停止旧容器。

latest 标签的特殊意义

latest 在 Docker 中有特殊的意义,需要特别注意:

  1. 默认标签

    • 当你在 docker pulldocker run 命令中不指定标签时,Docker 会自动使用 latest 标签。
    • 例如:docker pull nginx 等同于 docker pull nginx:latest
  2. 约定俗成的含义

    • latest 通常表示该镜像的最新稳定版本。
    • 它是 Docker 社区广泛接受的约定,用于标识最新的构建或发布版本。
  3. 自动更新行为

    • 当镜像仓库中的 latest 标签指向新的镜像时,下一次 docker pull 会拉取新的镜像。
    • 但这只在你显式执行 docker pull 时发生,已经运行的容器不会自动更新。
  4. 潜在问题

    • 版本不确定性latest 标签可能指向不同的镜像版本,这会导致环境之间的不一致性。
    • 缓存问题:如果本地已经有 latest 镜像,Docker 可能不会自动拉取新的 latest 镜像。
    • 部署风险:在生产环境中使用 latest 标签可能会导致不可预测的行为。
  5. 使用建议

    • 开发环境:在开发环境中使用 latest 标签是可以接受的,因为它方便快速迭代和测试。
    • 生产环境:在生产环境中,强烈建议使用明确的版本标签(如 v1.0.0, v2.1.3 等)。
    • CI/CD 流程:在自动化构建和部署流程中,建议使用版本化标签或 Git commit SHA 作为标签。

停止和删除容器

  1. 停止正在运行的容器:

    docker stop python-api-service
  2. 删除已停止的容器:

    docker rm python-api-service

    或者,你可以使用一条命令同时停止并删除容器:

    docker rm -f python-api-service
  3. (可选) 删除镜像:

    如果你不再需要该镜像,可以将其删除:

    docker rmi registry.cn-hangzhou.aliyuncs.com/<你的命名空间>/<你的镜像名>:<标签>
Responses