使

使用 GitHub Actions 和 S3 将 Django 完整的 CI-CD 流程迁移到 AWS

2025-06-07

使用 GitHub Actions 和 S3 将 Django 完整的 CI-CD 流程迁移到 AWS

本指南涵盖了使用 Amazon Beanstalk 和 GitHub Actions 为 Django 项目设置 CI-CD 工作流所需的所有步骤。

示例项目链接:https://github.com/vlntsolo/django-cicd

目录

  1. AWS Beanstalk 环境
  2. S3 配置
  3. IAM 用户访问
  4. GitHub 工作流程设置
  5. 准备 Django 设置
  6. 首次运行
  7. 编写部署后命令(钩子)

在我们开始之前,首先什么是 CI-CD 流程?

尽管与编译后的应用程序相比,Django 代码不需要任何构建步骤,但每次需要部署新功能或修复错误时,手动重新上传代码可能会让人感到很烦躁。因此,CI-CD(持续集成和持续交付)工作流应运而生。

CI-CD 工作流或流水线使我们能够在相对较短的时间内(通常只需几分钟)安全地构建、测试和部署 Web 应用程序。那么 Django 呢?如果您在 GitHub 上托管了一个 Python 应用程序代码库,那么在更新代码库后立即将其推送到托管环境将非常方便。这正是我们将使用 GitHub Actions 来实现的,该工具自 2019 年底起免费向公众开放。

让我们开始吧!

1. AWS Beanstalk 环境

在开始配置一切之前,我们需要确保我们的环境已经准备就绪。

如果您已有 AWS 账户,请前往控制台并搜索“Beanstalk”。如果没有,请在此处创建一个。系统将要求您添加账单信息才能继续。

在 Beanstalk 仪表板中,请确保在右上角选择了最合适的区域(要部署服务的区域)。勾选 [环境] 并选择 [创建新环境]。然后在弹出的对话框中,选择 [Web 服务器环境]。

创建 beanstalk python 环境

填写详细信息并关注平台部分。在这里我们需要选择 Python 平台(最新版本)和最新可用的 Amazon Linux 2。

退出示例应用程序并点击[创建环境]。片刻之后,您应该能够打开环境 URL 地址并查看示例页面。

打开环境页面,复制左上角显示的应用程序名称和环境。

这里要做的最后一件事是设置 Django 的数据库。

进入[配置] → [数据库]并选择首选选项:

在这个例子中,我选择了 PostgreSQL,因为这是我通常的选择,但如果您愿意,您可以坚持使用 MySQL 甚至 Oracle。

警告: 以这种方式创建的数据库服务器仅适用于测试目的。它将严格连接到环境。如果您删除或重新创建 Beanstalk 环境,数据库将被删除。在生产环境中,您应该使用VPC内的独立 RDS 或 Aurora 服务器。

现在我们已经有了托管的 Python 环境和数据库,我们需要为未来的应用程序构建准备一个文件存储。

2. S3 配置

在将构建推送到 Beanstalk 之前,我们需要设置一个自定义 S3 存储桶作为构建的临时存储。

在 AWS 控制台中搜索 S3 或从菜单中切换到它。然后选择[创建存储桶]。输入一个唯一的名称,并选择你的区域。

保留“阻止所有公共访问”复选框并继续[应用]

接下来我们需要做的是生成编程访问凭证,GitHub Action 将使用它来部署我们的 Django 应用程序。

3. IAM 用户访问 🔐

在 AWS 控制台中搜索 IAM 用户,并选择[添加用户]

在权限页面,选择 [直接附加现有策略]。搜索 S3FullAccess* 并选中复选框。对AdministratorAccess-AWSElasticBeanstalk * 重复相同步骤,然后点击[添加用户]

最后,复制上一步中的访问密钥 ID 和密钥。请确保将此信息保存在安全的地方,因为用户密钥只会显示一次。

看起来我们已经完成了 AWS 并准备继续使用 GitHub!

4. GitHub 工作流程设置

返回你的 Django 项目并创建一个名为 的文件夹.github。并在其中创建一个名为 workflows 的文件夹。GitHub Actions 配置应放置在其中,并使用 YAML 语法进行格式化。请参阅下面的示例:

#Location: .github/workflows/custom_config.yml

name: CI-CD pipeline to AWS
env:
  EB_S3_BUCKET_NAME: "YOUR BUCKET NAME FROM Step 2"
  EB_APPLICATION_NAME: "YOUR APP NAME FROM Step 1"
  EB_ENVIRONMENT_NAME: "YOUR ENVIRONMENT NAME FROM Step 1"
  DEPLOY_PACKAGE_NAME: "django-app-${{ github.sha }}.zip"
  AWS_REGION_NAME: "YOUR AWS REGION ("us-east-1"/"eu-central-1" etc.)"

on:
  push:
    branches:
      - master #Use your own branch here (Might be staging or testing)
jobs:
  build:
    runs-on: ubuntu-latest
    steps: 
      - name: Git clone on our repo
        uses: actions/checkout@v2

      - name: Create zip deployment package
        run: zip -r ${{ env.DEPLOY_PACKAGE_NAME }} ./ -x *.git*

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with: 
          aws-access-key-id: ${{ secrets.aws_access_key_id }}
          aws-secret-access-key: ${{ secrets.aws_secret_access_key }}
          aws-region: ${{ env.AWS_REGION_NAME }}
      - name: Copying file to S3
        run: aws s3 cp ${{ env.DEPLOY_PACKAGE_NAME }} s3://${{ env.EB_S3_BUCKET_NAME }}/
      - name: Print nice message on success finish
        run: echo "CI part finished successfuly"
  deploy:
    runs-on: ubuntu-latest
    needs: [build]
    steps:
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with: 
          aws-access-key-id: ${{ secrets.aws_access_key_id }}
          aws-secret-access-key: ${{ secrets.aws_secret_access_key }}
          aws-region: ${{ env.AWS_REGION_NAME }}

      - name: Create new EBL app ver
        run: |
          aws elasticbeanstalk create-application-version \
          --application-name ${{ env.EB_APPLICATION_NAME }} \
          --source-bundle S3Bucket="${{ env.EB_S3_BUCKET_NAME }}",S3Key="${{ env.DEPLOY_PACKAGE_NAME }}" \
          --version-label "${{ github.sha }}"

      - name: Deploy new app
        run: aws elasticbeanstalk update-environment --environment-name ${{ env.EB_ENVIRONMENT_NAME }} --version-label "${{ github.sha }}"
      - name: Print nice message on success finish
        run: echo "CD part finished successfuly"
Enter fullscreen mode Exit fullscreen mode

让我们深入了解一下配置块并检查它们的用途。更多详情请见此处。

1) [env]块作为配置中变量的快捷方式列表。我们在这里定义非敏感数据。

2)[jobs]块定义了实际要做的事情。

3) [build]块只是一个作业名称,其中包含构建过程中要执行的一系列“步骤”。对于纯 Django 应用来说,这仅意味着压缩工作目录并将其推送到 S3 存储桶。

4)[步骤]块列出了要在虚拟机上执行的名称和实际命令。

您可以轻松添加另一个名为测试的作业名称并在其中运行./manage.py 测试步骤。

5) [needs]块是进一步执行的先决条件。在我们的例子中,我们要确保在向 Beanstalk 发送命令之前,文件传输已成功完成。

6)[on]块指定触发事件,比如我们的“推送”,以及目标分支。

如果您有多个 Beanstalk 环境(QA、测试、登台、生产等),您需要为它们放置新的 config.yml 文件并相应地更改环境变量和分支。

您可能还注意到我们还没有定义secrets.aws_access_key_idsecrets.aws_secret_access_key。🧊 让我们解决这个问题!

打开你的 GitHub 仓库或为你的项目创建一个,然后前往[设置][密钥][新仓库密钥]。像这样粘贴你的 IAM 用户密钥和密钥:

重复同样的步骤,修改aws_secret_access_key and它的值。就这样!

5. 准备 Django 设置

还记得吗,我们在步骤 1 中将关系数据库连接到了 Beanstalk 环境?但是连接参数和数据库用户凭据在哪里呢?

通过集成数据库,Beanstalk 公开了可以立即使用的环境变量:

# main_django_app settings.py
import os

ALLOWED_HOSTS = ['YOUR_ENVIRONMENT_HOST']

DATABASES = {
'default': {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',
    'NAME': os.environ['RDS_DB_NAME'],
    'USER': os.environ['RDS_USERNAME'],
    'PASSWORD': os.environ['RDS_PASSWORD'],
    'HOST': os.environ['RDS_HOSTNAME'],
    'PORT': os.environ['RDS_PORT'],
    }
}

# rest of the settings
Enter fullscreen mode Exit fullscreen mode

不要忘记将您的环境 URL 和主域添加到允许的主机列表中。

此时,我们需要确保 Beanstalk Python 平台已准备好与 PostgreSQL 建立连接。让我们告诉它为我们安装一些附加组件。

在项目根目录中创建一个名为的文件夹.ebextensions并在其中放置一个文件01_packages.config

packages: 
  yum: 
    amazon-linux-extras: []

commands:
  01_postgres_activate: 
    command: sudo amazon-linux-extras enable postgresql10
  02_postgres_install: 
    command: sudo yum install -y postgresql-devel
Enter fullscreen mode Exit fullscreen mode

现在我们需要添加 Django 配置,以便将我们的主应用程序和设置告知 Beanstalk 的 WSGI 服务器。在.ebextensions文件夹中创建另一个名为的文件django.config

option_settings:
  aws:elasticbeanstalk:container:python:
    WSGIPath: main_django_app.wsgi:application
  aws:elasticbeanstalk:application:environment:
    DJANGO_SETTINGS_MODULE: main_django_app.settings
    "PYTHONPATH": "/var/app/current:$PYTHONPATH"
  aws:elasticbeanstalk:environment:proxy:staticfiles:
    /static: static
Enter fullscreen mode Exit fullscreen mode

将main_django_app更改为您的 Django 应用程序名称。

最后一行aws:elasticbeanstalk:environment:proxy:staticfiles0:告诉通过反向代理提供哪个文件夹以及使用哪个相对 URL。

最后,使用冻结您的本地 python 环境pip freeze > requirements.txt(它将成为 Beanstalk 配置 EC2 环境的主要来源)。

6. 首次运行🔥

将所有更改推送到您指定的分支,然后访问“操作”选项卡。如果操作成功完成,您将看到绿色标记。如果出现问题,请打开日志并解决其中的错误。

GitHub Actions 成功运行后出现错误?请访问 Elastic Beanstalk 环境并检查日志。

希望您能看到类似这样的内容:

7. 编写部署后命令(钩子)🔌

部署后仍有几个命令需要执行。

1)我们需要将我们的更改迁移到 Beanstalk 数据库(makemigrations 命令创建的迁移文件应该是代码库的一部分)。

2)我们需要收集静态文件(不需要将静态文件保存在代码库中)。

这个问题可以通过 Beanstalk 的部署后钩子解决。文件名可以完全自定义,但文件扩展名很重要。所有 .sh 文件都将按字母数字顺序执行。

在项目根目录中,创建.platform具有以下结构的文件夹:

.platform/
└───hooks/
    └───postdeploy/
        -01_django.sh
Enter fullscreen mode Exit fullscreen mode
#!/bin/bash

source /var/app/venv/*/bin/activate && {

# collecting static files
python manage.py collectstatic --noinput;
# log which migrations have already been applied
python manage.py showmigrations;
# migrate the rest
python manage.py migrate --noinput;
# another command to create a superuser (write your own)
}
Enter fullscreen mode Exit fullscreen mode

你已经明白了!现在,你可以了解如何创建超级用户帐户了。

⚠️重要提示:

查看 IAM 用户访问策略。出于教程目的,我已授予 S3 和 Beanstalk 的完全访问权限。请确保仅授予 GitHub Actions 客户端所需的权限,以防止密钥泄露造成不良后果。

–为 S3 存储桶和应用程序版本存储添加生命周期规则。默认情况下,S3 不会从存储桶中删除应用程序版本或任何其他文件。在 S3 和 Beanstalk 中使用生命周期规则,可以仅保留所需的应用程序版本。

由于 Django 标头中的 ALLOWED_HOSTS 限制,AWS Beanstalk 健康检查系统可能无法正常工作(严重健康状态)。我不知道该如何正确处理这个问题(您可以忽略状态警告,或者ALLOWED_HOSTS = ['*']自行承担风险)。

– 如果您要使用 PostgreSQL,请不要忘记安装软件包pip install psycopg2-binary并冻结 requirements.txt。

有用的链接:

如何为不同的环境拆分 Django 设置
如何在 AL2 Beanstalk 上使用 Supervisor 配置 Django Q
将 Django 应用程序部署到 Elastic Beanstalk
GitHub Actions 的工作流语法

希望你喜欢本指南。敬请期待,下次我可能会介绍如何搭建一个基于 Django 的全栈项目,并带来真正无缝的开发体验。

本文最初发表在我的博客文章中

文章来源:https://dev.to/vlntsolo/django-full-ci-cd-flow-to-aws-with-github-actions-and-s3-2enp
PREV
GPT-4o:逐步了解如何在新模型上实现 RAG!
NEXT
React 组件生命周期