GitHub 작업을 사용하여 CI/CD 파이핑 생성

24494 단어 pythonawsgithubdocker
팀으로서 EC2를 테스트 서버로 사용합니다.하지만 우리는 두 가지 문제에 직면해 있다.
  • 새 제출을 전송할 때마다 ssh 키와git pull로 서버에 접근해야 합니다.
  • "그것은 내 기계에서 일하지만......"

  • CI/CD 파이프를 어떻게 설치하는지 배울 때가 된 것 같습니다.그러나 먼저 CI/CD란 무엇입니까?

    CI/CD is a method to frequently deliver apps to customers by introducing automation into the stages of app development. The main concepts attributed to CI/CD are continuous integration, continuous delivery, and continuous deployment. CI/CD is a solution to the problems integrating new code can cause for development and operations teams (AKA "integration hell").
    source: What is CI/CD?


    파이프는 이 과정을 틈새 없이 한다.
    시작하기 전에 EC2 인스턴스를 생성합니다.그리고 docker와github를 사용하여fastAPI 프로그램을 배치합니다. (이것은fastAPI 프로그램이 아니라 백엔드 프로그램도 가능합니다.)이 점을 해낼 수 있는 방법은 매우 많다.두 개 보여줄게.

    자동 Git Pull


    요구 사항
  • FastapI 어플리케이션
  • Docker
  • docker compose
  • GitHub
  • AWS EC2
  • 애플리케이션 아카이빙


    docker compose를 사용하면 다중 용기 docker 프로그램을 정의하고 실행할 수 있습니다.여기에는 두 가지 서비스가 있다.
    # docker-compose.yaml
    version: "3.3"
    services:
      mysqldb:
        image: "mysql"
        ports:
          - "3306:3306"
        volumes:
          - data:/data/db
          - ./env/mysql.env:/env/mysql.env
        env_file:
          - ./env/mysql.env
      app:
        build: {the path where your Dockerfile is}
        restart: always
        ports:
          - "8000:8000"
        volumes:
          - ./env/.env:/env/.env
        env_file:
          - ./env/.env
        links:
          - mysqldb
        depends_on:
          - mysqldb
    
    volumes:
      data:
    
    첫 번째는 MySQL 데이터베이스입니다.image: "mysql"를 사용하면 EC2 기기에 MySQL을 설치하지 않고도 docker hub에서 MySQL 이미지를 추출할 수 있습니다.특정 버전image: "mysql:{version}"을 사용하려는 경우
    CI/CD 파이프라인을 구축하고 있습니다.만약 데이터베이스에 있는 데이터를 우리가 배치할 때 잃어버린다면 이것은 빈틈없는 체험이 되지 않겠습니까?데이터를 보존하려면 볼륨을 사용하십시오.
    mysqldb:
      image: "mysql"
      ports:
        - "3306:3306"
      volumes:
        - data:/data/db
        - ./env/mysql.env:/env/mysql.env
      env_file:
        - ./env/mysql.env
    ...
    volumes:
        data:
    
    다음은 니 신청이야.build:가 Dockerfile이 있는 디렉토리를 가리키는지 확인합니다.
    app:
      build: ./
      restart: always
      ports:
        - "8000:8000"
      volumes:
        - ./env/.env:/env/.env
      env_file:
        - ./env/.env
      links:
        - mysqldb
      depends_on:
        - mysqldb
    
    보안 문제로 프로필을github에 제출하는 것은 좋은 생각이 아닙니다.그러나, 우리는github 조작을 통해 자동화 배치 작업을 희망한다.프로파일을 생략하면 파일을 찾아 가져올 수 없으므로 응용 프로그램을 시작할 수 없습니다.
    이 문제를 피하기 위해git는 EC2 기기에서 끌어내어 기기 (설정 변수가 있음) 와 용기 (비어 있음) 에서 프로필을 만듭니다.컨테이너의 파일과 연결된 마운트를 사용하여 실행되는 컴퓨터와 데이터를 공유할 수 있습니다.
    # Dockerfile
    FROM python:3.9
    
    WORKDIR /
    
    ENV DOCKERIZE_VERSION v0.2.0
    
    RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \  
        && tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz
    
    COPY ./requirements.txt /requirements.txt
    
    RUN pip install --upgrade pip
    
    RUN pip install --no-cache-dir --upgrade -r /requirements.txt
    
    COPY . .
    
    RUN touch env/.env
    
    RUN touch env/mysql.env
    
    RUN chmod +x docker-entrypoint.sh
    
    ENTRYPOINT ./docker-entrypoint.sh
    
    EXPOSE 8000
    
    CMD ["python", "app/main.py"]
    
    # docker-compose.yaml
    ...
    volumes:
        ...
      - ./env/mysql.env:/env/mysql.env
    ...
    volumes:
      - ./env/.env:/env/.env
    ...
    
    # Dockerfile
    ...
    RUN touch env/.env # creates env file in container
    
    RUN touch env/mysql.env # creates env file in container
    ...
    

    Note that I'm trying to create development environment. Bind Mounts are not meant to be used in production.


    이것들은 내가 EC2 기계에 있는 환경 파일들이다.
    # env/.env
    JWT_ALGORITHM=****
    JWT_SECRET_KEY=****
    SQLALCHEMY_DATABASE_URL=mysql+pymysql://{MYSQL_USER}:{MYSQL_PASSWORD}@mysqldb:3306/{MYSQL_DATABASE}
    
    # env/mysql.env
    MYSQL_USER=****
    MYSQL_PASSWORD=****
    MYSQL_ROOT_PASSWORD=****
    MYSQL_DATABASE=****
    
    docker compose에 depends_on: mysqldb가 있기 때문이다.yaml, 컨테이너에 자동으로 네트워크를 구축합니다.따라서, 우리는 docker compose에서 정의한 이름으로 데이터베이스 URL을 정의할 수 있습니다.yaml(mysqldb).
    # docker-entrypoint.sh
    dockerize -wait tcp://mysqldb:3306  -timeout 20s
    
    echo "Start server"
    alembic upgrade head
    python /app/main.py
    
    dockerizedocker 용기에서 실행되는 프로그램을 간소화하는 실용 프로그램입니다.그 밖에 다른 서비스의 제공을 기다려야만 했다.MySQL 용기는 프로그램이 시작되기 전에 '시작할 준비가 되어 있어야 합니다.' 그래서 이 도구를 사용했습니다.

    GitHub 워크플로우 작성


    먼저 EC2 시스템에서 저장소를 복제하고 env 파일을 만듭니다.
    그럼 행동의 비밀을 설정하자.저장소에서 설정 > Confidential 로 이동합니다.New repository secret를 누르면github 작업 기간에 사용할 환경 변수를 정의할 수 있습니다.
    응용 프로그램 환경 값과 EC2 자격 증명을 추가합니다.


    AWS EC2 PEM의 경우 이것을 선택합니다.
    set up a workflow your self를 클릭하고 Github 워크플로우를 작성합니다.


    # .github/workflows/main.yml
    name: CI/CD Docker
    
    on:
      push:
        branches:
          - main
      pull_request:
        branches:
          - main
    
    jobs:
      Integration:
        timeout-minutes: 3
        runs-on: ubuntu-latest
        steps:
          - name: Checkout
            uses: actions/checkout@v1
          - name: Create env file
            env:
              JWT_ALGORITHM: ${{ secrets.JWT_ALGORITHM }}
              JWT_SECRET_KEY: ${{ secrets.JWT_SECRET_KEY }}
              SQLALCHEMY_DATABASE_URL: ${{ secrets.SQLALCHEMY_DATABASE_URL }}
              MYSQL_USER: ${{ secrets.MYSQL_USER }}
              MYSQL_PASSWORD: ${{ secrets.MYSQL_PASSWORD }}
              MYSQL_ROOT_PASSWORD: ${{ secrets.MYSQL_ROOT_PASSWORD }}
              MYSQL_DATABASE: ${{ secrets.MYSQL_DATABASE }}
            run: |
              mkdir env
              touch ./env/.env
              echo JWT_ALGORITHM="$JWT_ALGORITHM" >> ./env/.env
              echo JWT_SECRET_KEY="$JWT_SECRET_KEY" >> ./env/.env
              echo SQLALCHEMY_DATABASE_URL="$SQLALCHEMY_DATABASE_URL" >> ./env/.env
              ls -a
              cat env/.env
              touch ./env/mysql.env
              echo MYSQL_USER="$MYSQL_USER" >> ./env/mysql.env
              echo MYSQL_PASSWORD="$MYSQL_PASSWORD" >> ./env/mysql.env
              echo MYSQL_ROOT_PASSWORD="$MYSQL_ROOT_PASSWORD" >> ./env/mysql.env
              echo MYSQL_DATABASE="$MYSQL_DATABASE" >> ./env/mysql.env
              ls -a
              cat env/mysql.env
            shell: bash
          - name: Start containers
            run: docker-compose up -d
    
      Deployment:
        needs: Integration
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v2
          - name: Git pull
            env:
              AWS_EC2_PEM: ${{ secrets.AWS_EC2_PEM  }}
              AWS_EC2_PUBLIC_IP: ${{ secrets.AWS_EC2_PUBLIC_IP  }}
              AWS_EC2_USERNAME: ${{ secrets.AWS_EC2_USERNAME  }}
            run: |
              pwd
              echo "$AWS_EC2_PEM" > private_key && chmod 600 private_key
              ssh -o StrictHostKeyChecking=no -i private_key ${AWS_EC2_USERNAME}@${AWS_EC2_PUBLIC_IP} '
                cd {/path/to/your/project/directory} &&
                git checkout main &&
                git fetch --all &&
                git reset --hard origin/main &&
                git pull origin main &&
                docker-compose up -d --build
              '
    

    GitHub 컨테이너 레지스트리 사용


    여기서 GHCR(GitHub 컨테이너 레지스트리)을 사용합니다.컨테이너 레지스트리는 컨테이너 이미지를 저장하는 저장소(또는 저장소의 컬렉션)입니다.
    요구 사항
  • FastapI 어플리케이션
  • Docker
  • AWS EC2
  • AWS RDS
  • GitHub
  • 응용 프로그램 중지


    이번에는 MySQL 용기 대신 RDS를 사용할 것이기 때문에, 이전보다 응용 프로그램에 대한 dockerize를 하는 것이 훨씬 간단합니다.
    FROM python:3.9
    
    WORKDIR /
    
    COPY ./requirements.txt /requirements.txt
    
    RUN pip install --no-cache-dir --upgrade -r /requirements.txt
    
    COPY . .
    
    EXPOSE 8000
    
    RUN touch .env
    
    CMD ["python", "app/main.py"]
    

    GitHub 워크플로우 작성


    github 조작을 위한 영패를 생성합니다.개인 정보를 클릭하여 설정 > 개발자 설정 > 개인 방문 영패에 들어가세요.

    범위 내에서는 repo, workflowpackages를 선택합니다.
    영패를 복사해서 actions secrets에 붙이고 다른 기밀을 추가합니다.

    github 메모리 라이브러리에서 설정 > 조작 > 달리기 선수로 이동하고 New self-hosted runner를 누르십시오.
    당신의 EC2 기계를 위해 정확한 조작 시스템을 선택하고 기계에서 지도에 따라 조작하세요.
    ./run.sh 명령을 사용하여 실행하기 전에 워크플로우 파일을 구성합니다.
    name: CI/CD Docker
    
    on:
      push:
        branches:
          - main
    env:
      DOCKER_IMAGE: ghcr.io/ninahwang/cicd_2 # this should be lower case !
      VERSION: ${{ github.sha }}
    
    jobs:
      build:
        name: Build
        runs-on: ubuntu-latest
        steps:
          - name: Check out source code
            uses: actions/checkout@v2
          - name: Set up docker buildx
            id: buildx
            uses: docker/setup-buildx-action@v1
          - name: Cache docker layers
            uses: actions/cache@v2
            with:
              path: /tmp/.buildx-cache
              key: ${{ runner.os }}-buildx-${{ env.VERSION }}
              restore-keys: |
                ${{ runner.os }}-buildx-
          - name: Login
            uses: docker/login-action@v1
            with:
              registry: ghcr.io
              username: ${{ github.actor }}
              password: ${{ secrets.TOKEN }}
          - name: Build and push
            id: docker_build
            uses: docker/build-push-action@v2
            with:
              builder: ${{ steps.buildx.outputs.name }}
              push: ${{ github.event_name != 'pull_request' }}
              tags: ${{ env.DOCKER_IMAGE }}:${{ env.VERSION }}
    
      deploy:
        needs: build
        name: Deploy
        runs-on: [self-hosted]
        steps:
          - name: Login to ghcr
            uses: docker/login-action@v1
            with:
              registry: ghcr.io
              username: ${{ github.actor }}
              password: ${{ secrets.TOKEN }}
          - name: Create .env file
            env:
              JWT_ALGORITHM: ${{ secrets.JWT_ALGORITHM }}
              JWT_SECRET_KEY: ${{ secrets.JWT_SECRET_KEY }}
              SQLALCHEMY_DATABASE_URL: ${{ secrets.SQLALCHEMY_DATABASE_URL }}
            run: |
              touch .env
              echo JWT_ALGORITHM="$JWT_ALGORITHM" >> .env
              echo JWT_SECRET_KEY="$JWT_SECRET_KEY" >> .env
              echo SQLALCHEMY_DATABASE_URL="$SQLALCHEMY_DATABASE_URL" >> .env
            shell: bash
          - name: Docker run
            run: |
              docker ps -q --filter "name=cicd_2" | grep -q . && docker stop cicd_2 && docker rm -fv cicd_2
              docker run -p 8000:8000 -d -v "$(pwd)/.env:/.env" --restart always --name cicd_2 ${{ env.DOCKER_IMAGE }}:${{ env.VERSION }}
    
    현재 실행 중run.sh.

    좋은 웹페이지 즐겨찾기