如何使用 Github Actions 发布对 Docker 镜像的更改

Posted

技术标签:

【中文标题】如何使用 Github Actions 发布对 Docker 镜像的更改【英文标题】:How to publish changes to Docker images using Github Actions 【发布时间】:2022-01-24 02:39:31 【问题描述】:

我正在使用 Docker 和 GitHub Packages/Actions 开发 CI/CD 管道。我有 2 个工作流程:build.ymldeploy.yml

build.yml 工作流应该从 GitHub Packages 中提取 Docker 镜像,构建它们,运行自动化测试,然后将新镜像推送到 GitHub Packages。

deploy.yml 工作流将图像拉到服务器并运行它们。

我遇到的问题是我的本地更改没有在服务器上更新。

build.yml

name: Build and Test

on:
  push:
    branches:
      - development

env:
  BACKEND_IMAGE: ghcr.io/$(echo $GITHUB_REPOSITORY | tr '[:upper:]' '[:lower:]')/backend
  FRONTEND_IMAGE: ghcr.io/$(echo $GITHUB_REPOSITORY | tr '[:upper:]' '[:lower:]')/frontend
  nginx_IMAGE: ghcr.io/$(echo $GITHUB_REPOSITORY | tr '[:upper:]' '[:lower:]')/nginx

jobs:
  test:
    name: Build Images and Run Automated Tests
    runs-on: ubuntu-latest
    steps:
      - name: Checkout master
        uses: actions/checkout@v1
      - name: Add environment variables to .env
        run: |
          echo DEBUG=0 >> .env
          echo SQL_ENGINE=django.db.backends.postgresql >> .env
          echo DATABASE=postgres >> .env
          echo SECRET_KEY=$ secrets.SECRET_KEY  >> .env
          echo SQL_DATABASE=$ secrets.SQL_DATABASE  >> .env
          echo SQL_USER=$ secrets.SQL_USER  >> .env
          echo SQL_PASSWORD=$ secrets.SQL_PASSWORD  >> .env
          echo SQL_HOST=$ secrets.SQL_HOST  >> .env
          echo SQL_PORT=$ secrets.SQL_PORT  >> .env
      - name: Set environment variables
        run: |
          echo "BACKEND_IMAGE=$(echo $env.BACKEND_IMAGE )" >> $GITHUB_ENV
          echo "FRONTEND_IMAGE=$(echo $env.FRONTEND_IMAGE )" >> $GITHUB_ENV
          echo "NGINX_IMAGE=$(echo $env.NGINX_IMAGE )" >> $GITHUB_ENV
      - name: Log in to GitHub Packages
        run: echo $PERSONAL_ACCESS_TOKEN | docker login ghcr.io -u $ secrets.NAMESPACE  --password-stdin
        env:
          PERSONAL_ACCESS_TOKEN: $ secrets.PERSONAL_ACCESS_TOKEN 
      - name: Pull images
        run: |
          docker pull $ env.BACKEND_IMAGE  || true
          docker pull $ env.FRONTEND_IMAGE  || true
          docker pull $ env.NGINX_IMAGE  || true
      - name: Build images
        run: |
          docker-compose -f docker-compose.ci.yml build
      - name: Run Backend Tests
        run: |
          docker-compose -f docker-compose.ci.yml run backend python manage.py test
      - name: Push images
        run: |
          docker push $ env.BACKEND_IMAGE 
          docker push $ env.FRONTEND_IMAGE 
          docker push $ env.NGINX_IMAGE 

docker-compose.ci.yml

version: "3.8"

services:
  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile.prod
    command: gunicorn backend.wsgi:application --bind 0.0.0.0:8000
    volumes:
      - ./backend:/backend
      - static_volume:/static
      - media_volume:/media
    expose:
      - 8000
    env_file: .env
  frontend:
    build:
      context: ./frontend
    volumes:
      - frontend_build:/frontend/build
  nginx:
    build:
      context: ./nginx
    ports:
      - 80:80
    volumes:
      - frontend_build:/var/www/frontend
    depends_on:
      - backend
      - frontend

volumes:
  frontend_build:
  static_volume:
  media_volume:

后端/Dockerfile.prod

FROM python:3.9.5-alpine
WORKDIR /backend
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
RUN apk update \
    && apk add --virtual build-deps gcc python3-dev musl-dev \
    && apk add postgresql-dev \
    && pip install psycopg2 \
    && apk del build-deps
RUN pip install --upgrade pip
COPY ./requirements.txt /requirements.txt
RUN pip install -r /requirements.txt
COPY ./entrypoint.prod.sh /entrypoint.prod.sh
COPY . /backend/
ENTRYPOINT ["/entrypoint.prod.sh"]

我尝试了一些不同的方法都无济于事。任何帮助理解为什么我的更改没有更新将不胜感激!

【问题讨论】:

发布Dockerfile,上面有如何构建图像的说明,它可能就在那里.. 虽然不看Dockerfile的第一个猜测是您正在构建的图像不包含您的代码..(因为卷- ./backend:/backend) - 您应该将您的代码复制到创建的图像 我在帖子中添加了 Dockerfile 内容。我尝试使用和删除后端卷均无济于事。想法? 为什么会有拉取图片的步骤?您可以删除它..您需要使用新标签构建图像.. 【参考方案1】:

您似乎正在重新推送您提取的相同图像,而不是构建的图像。为了验证这一点,您可以删除Pull images 步骤以确认。

如果是这种情况,您可以更改在docker-compose.ci.yml 中标记图像的方式,或更改在Push images 步骤中推送的图像。

或者,您可以使用记录在案的流程 here 并稍作改动:

name: Create and publish a Docker image

on:
  push:
    branches: ['release']

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: $ github.repository 

jobs:
  build-and-push-image:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@v2

      - name: Log in to the Container registry
        uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
        with:
          registry: $ env.REGISTRY 
          username: $ github.actor 
          password: $ secrets.GITHUB_TOKEN 

      - name: Extract metadata (tags, labels) for Docker
        id: meta
        uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
        with:
          images: $ env.REGISTRY /$ env.IMAGE_NAME 

      - name: Build and push backend Docker image
        uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
        with:
          context: ./backend # <<<=== Notice this
          file: Dockerfile.prod # <<<=== Notice this
          push: true
          tags: $ steps.meta.outputs.tags 
          labels: $ steps.meta.outputs.labels 

为前端添加另一个Dockerfile,并为其复制最后一步。

【讨论】:

以上是关于如何使用 Github Actions 发布对 Docker 镜像的更改的主要内容,如果未能解决你的问题,请参考以下文章

如何使用带有语义发布 Github 插件的 Github Actions 发布整个目录?

如何使用 Github Actions 进行 SFTP?

如何从 GitHub Actions 获取我的日志文件?

如何在 GitHub Actions 中使用最新发布标签?

如何使用可重用的Github Actions和Heroku构建简单的部署管道

如何使用 Github-actions 在 Docker 上使用 Mysql 运行 Prisma 迁移