From 5ae22adfce811d8cff1ed9d565fe9237b93ab322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=80=EB=AF=BC?= <108014449+stopmin@users.noreply.github.com> Date: Mon, 8 Jul 2024 11:32:26 +0900 Subject: [PATCH 1/3] =?UTF-8?q?Docker=20File=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EB=B0=8F=20ECS=20=EB=B0=B0=ED=8F=AC=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * python version 3.12.4로 업그레이드 * 도커파일 정의 및 pipfile 업데이트 * ECS Deploy 설정 --- .github/workflows/deploy-ecs.yml | 204 +++++++++++++++++++++++++++++++ Dockerfile | 21 ++++ Pipfile | 2 +- Pipfile.lock | 109 +++++++++-------- entrypoint.sh | 4 + 5 files changed, 287 insertions(+), 53 deletions(-) create mode 100644 .github/workflows/deploy-ecs.yml create mode 100644 Dockerfile create mode 100644 entrypoint.sh diff --git a/.github/workflows/deploy-ecs.yml b/.github/workflows/deploy-ecs.yml new file mode 100644 index 0000000..53268d0 --- /dev/null +++ b/.github/workflows/deploy-ecs.yml @@ -0,0 +1,204 @@ +name: Deploy to Amazon ECS + +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + +on: + push: + branches: [ "staging" ] + +env: + AWS_REGION: ap-northeast-2 # AWS region 설정 + ECR_REPOSITORY: gyeongdan-fastapi # Amazon ECR repository 이름 + ECS_SERVICE: GyeongdanFastAPI # Amazon ECS 서비스 이름 + ECS_CLUSTER: gyeongdan # Amazon ECS 클러스터 이름 + ECS_TASK_DEFINITION: tf-gyeongdan-fastapi.json # Amazon ECS task definition 파일 경로 + CONTAINER_NAME: FastAPI # 컨테이너 이름 + PROGRESS_SLACK_CHANNEL: C07BRCDNBMF # Slack 채널 ID + +permissions: + contents: read + +jobs: + deploy: + name: Deploy + runs-on: ubuntu-latest-8-cores + + steps: + - name: Post Slack Channel that Build Start + id: slack-build-start + uses: slackapi/slack-github-action@v1.23.0 + with: + channel-id: ${{ env.PROGRESS_SLACK_CHANNEL }} + payload: | + { + "text": ":small_airplane: *Gyeongdan FastAPI ${{ github.ref_name }}* 배포가 시작되었습니다.", + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": ":mega: *Gyeongdan FastAPI ${{ github.ref_name }}* 배포가 시작되었습니다." + } + }, + { + "type": "actions", + "elements": [ + { + "type": "button", + "text": { + "type": "plain_text", + "emoji": true, + "text": "깃허브액션에서 확인하기." + }, + "value": "click_me_123", + "url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" + } + ] + } + ] + } + env: + SLACK_BOT_TOKEN: ${{ secrets.PROGRESS_SLACK_CHANNEL_TOKEN }} + + - name: Checkout + uses: actions/checkout@v4 + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v2 + 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: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v1 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Docker build & Push Docker image to Amazon ECR + id: build-image + uses: docker/build-push-action@v5 + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + IMAGE_TAG: ${{ github.sha }} + with: + context: . + push: true + tags: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }} + build-args: | + DATABASE_USERNAME=${{ secrets.GYEONGDAN_DB_USERNAME }} + DATABASE_PASSWORD=${{ secrets.GYEONGDAN_DB_PASSWORD }} + cache-from: type=gha + cache-to: type=gha,mode=min,ignore-error=true + + - name: Fill in the new image ID in the Amazon ECS task definition + id: task-def + uses: aws-actions/amazon-ecs-render-task-definition@v1 + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + IMAGE_TAG: ${{ github.sha }} + with: + task-definition: ${{ env.ECS_TASK_DEFINITION }} + container-name: ${{ env.CONTAINER_NAME }} + image: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }} + + - name: Deploy Amazon ECS task definition + id: ecs-deploy + uses: aws-actions/amazon-ecs-deploy-task-definition@v1 + with: + task-definition: ${{ steps.task-def.outputs.task-definition }} + service: ${{ env.ECS_SERVICE }} + cluster: ${{ env.ECS_CLUSTER }} + wait-for-service-stability: true + wait-for-minutes: 10 + + - name: Verify New Task Definition is Deployed + run: | + CURRENT_TASK_DEF_ARN=$(aws ecs describe-services --cluster ${{ env.ECS_CLUSTER }} --service ${{ env.ECS_SERVICE }} --query services[0].deployments[0].taskDefinition | jq -r ".") + NEW_TASK_DEF_ARN=${{ steps.ecs-deploy.outputs.task-definition-arn }} + echo "Current task arn: $CURRENT_TASK_DEF_ARN" + echo "New task arn: $NEW_TASK_DEF_ARN" + if [ "$CURRENT_TASK_DEF_ARN" != "$NEW_TASK_DEF_ARN" ]; then + echo "Deployment failed." + exit 1 + fi + + - name: Post Slack Channel that Build Success + if: success() + id: slack-build-success + uses: slackapi/slack-github-action@v1.23.0 + with: + channel-id: ${{ env.PROGRESS_SLACK_CHANNEL }} + payload: | + { + "text": ":white_check_mark: *Gyeongdan FastAPI ${{ github.ref_name }}* 배포가 성공했습니다.", + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": ":pepe_cheer: *Gyeongdan FastAPI ${{ github.ref_name }}* 배포가 성공했습니다." + } + }, + { + "type": "actions", + "elements": [ + { + "type": "button", + "text": { + "type": "plain_text", + "emoji": true, + "text": "깃허브액션에서 확인하기." + }, + "style": "primary", + "value": "click_me_123", + "url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" + } + ] + } + ] + } + env: + SLACK_BOT_TOKEN: ${{ secrets.PROGRESS_SLACK_CHANNEL_TOKEN }} + + - name: Post Slack Channel that Build Fail + if: failure() + id: slack-build-fail + uses: slackapi/slack-github-action@v1.23.0 + with: + channel-id: ${{ env.PROGRESS_SLACK_CHANNEL }} + payload: | + { + "text": ":x: *Gyeongdan FastAPI ${{ github.ref_name }}* 배포가 실패했습니다.", + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": ":pepe_rainy: *Gyeongdan FastAPI ${{ github.ref_name }}* 배포가 실패했습니다." + } + }, + { + "type": "actions", + "elements": [ + { + "type": "button", + "text": { + "type": "plain_text", + "emoji": true, + "text": "깃허브액션에서 확인하기." + }, + "style": "danger", + "value": "click_me_123", + "url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" + } + ] + } + ] + } + env: + SLACK_BOT_TOKEN: ${{ secrets.PROGRESS_SLACK_CHANNEL_TOKEN }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d2d2c33 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +FROM --platform=linux/amd64 python:3.12.4-slim-bookworm + +WORKDIR /app + +RUN apt-get update && \ + apt-get install -y --no-install-recommends gcc libpq-dev && \ + pip install --no-cache-dir pipenv && \ + apt-get purge -y --auto-remove gcc && \ + rm -rf /var/lib/apt/lists/* + +COPY Pipfile Pipfile.lock ./ +RUN pipenv install --deploy --ignore-pipfile + +COPY ./entrypoint.sh ./entrypoint.sh +COPY ./app ./app + +ENV PORT=8000 + +RUN chmod +x ./entrypoint.sh + +ENTRYPOINT ["/bin/sh", "-c", "./entrypoint.sh"] diff --git a/Pipfile b/Pipfile index 4e68c39..cdd0161 100644 --- a/Pipfile +++ b/Pipfile @@ -31,4 +31,4 @@ python-dotenv = "*" [requires] python_version = "3.12" -python_full_version = "3.12.3" +python_full_version = "3.12.4" diff --git a/Pipfile.lock b/Pipfile.lock index fa35d10..155211c 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,11 +1,11 @@ { "_meta": { "hash": { - "sha256": "09d83d8b6da2289fa4357747121deb4a89bbf55cffc2e591d460238c8c9e99c7" + "sha256": "1a8e880d24fe4f7a7f2ba47534ff161b542f6b3036de0e649c4b0c4c79473860" }, "pipfile-spec": 6, "requires": { - "python_full_version": "3.12.3", + "python_full_version": "3.12.4", "python_version": "3.12" }, "sources": [ @@ -700,64 +700,69 @@ }, "openai": { "hashes": [ - "sha256:009bfa1504c9c7ef64d87be55936d142325656bbc6d98c68b669d6472e4beb09", - "sha256:3d1e0b0aac9b0db69a972d36dc7efa7563f8e8d65550b27a48f2a0c2ec207e80" + "sha256:4f5c1b90526cf48eaedac7b32d11b5c92fa7064b82617ad8f5f3279cd9ef090d", + "sha256:d73d353bcc0bd46b9516e78a0c6fb1cffaaeb92906c7c7b467c4fa088332a150" ], "index": "pypi", "markers": "python_full_version >= '3.7.1'", - "version": "==1.35.7" + "version": "==1.35.9" }, "orjson": { "hashes": [ - "sha256:03b565c3b93f5d6e001db48b747d31ea3819b89abf041ee10ac6988886d18e01", - "sha256:099e81a5975237fda3100f918839af95f42f981447ba8f47adb7b6a3cdb078fa", - "sha256:10c0eb7e0c75e1e486c7563fe231b40fdd658a035ae125c6ba651ca3b07936f5", - "sha256:1146bf85ea37ac421594107195db8bc77104f74bc83e8ee21a2e58596bfb2f04", - "sha256:1670fe88b116c2745a3a30b0f099b699a02bb3482c2591514baf5433819e4f4d", - "sha256:185c394ef45b18b9a7d8e8f333606e2e8194a50c6e3c664215aae8cf42c5385e", - "sha256:1ad1de7fef79736dde8c3554e75361ec351158a906d747bd901a52a5c9c8d24b", - "sha256:235dadefb793ad12f7fa11e98a480db1f7c6469ff9e3da5e73c7809c700d746b", - "sha256:28afa96f496474ce60d3340fe8d9a263aa93ea01201cd2bad844c45cd21f5268", - "sha256:2d97531cdfe9bdd76d492e69800afd97e5930cb0da6a825646667b2c6c6c0211", - "sha256:338fd4f071b242f26e9ca802f443edc588fa4ab60bfa81f38beaedf42eda226c", - "sha256:36a10f43c5f3a55c2f680efe07aa93ef4a342d2960dd2b1b7ea2dd764fe4a37c", - "sha256:3d21b9983da032505f7050795e98b5d9eee0df903258951566ecc358f6696969", - "sha256:51bbcdea96cdefa4a9b4461e690c75ad4e33796530d182bdd5c38980202c134a", - "sha256:53ed1c879b10de56f35daf06dbc4a0d9a5db98f6ee853c2dbd3ee9d13e6f302f", - "sha256:545d493c1f560d5ccfc134803ceb8955a14c3fcb47bbb4b2fee0232646d0b932", - "sha256:584c902ec19ab7928fd5add1783c909094cc53f31ac7acfada817b0847975f26", - "sha256:5a35455cc0b0b3a1eaf67224035f5388591ec72b9b6136d66b49a553ce9eb1e6", - "sha256:5df58d206e78c40da118a8c14fc189207fffdcb1f21b3b4c9c0c18e839b5a214", - "sha256:64c9cc089f127e5875901ac05e5c25aa13cfa5dbbbd9602bda51e5c611d6e3e2", - "sha256:68f85ecae7af14a585a563ac741b0547a3f291de81cd1e20903e79f25170458f", - "sha256:6970ed7a3126cfed873c5d21ece1cd5d6f83ca6c9afb71bbae21a0b034588d96", - "sha256:6b68742c469745d0e6ca5724506858f75e2f1e5b59a4315861f9e2b1df77775a", - "sha256:7a5baef8a4284405d96c90c7c62b755e9ef1ada84c2406c24a9ebec86b89f46d", - "sha256:7d10cc1b594951522e35a3463da19e899abe6ca95f3c84c69e9e901e0bd93d38", - "sha256:85c89131d7b3218db1b24c4abecea92fd6c7f9fab87441cfc342d3acc725d807", - "sha256:8a11d459338f96a9aa7f232ba95679fc0c7cedbd1b990d736467894210205c09", - "sha256:8c13ca5e2ddded0ce6a927ea5a9f27cae77eee4c75547b4297252cb20c4d30e6", - "sha256:9cd684927af3e11b6e754df80b9ffafd9fb6adcaa9d3e8fdd5891be5a5cad51e", - "sha256:b2efbd67feff8c1f7728937c0d7f6ca8c25ec81373dc8db4ef394c1d93d13dc5", - "sha256:b39e006b00c57125ab974362e740c14a0c6a66ff695bff44615dcf4a70ce2b86", - "sha256:b6c8e30adfa52c025f042a87f450a6b9ea29649d828e0fec4858ed5e6caecf63", - "sha256:be79e2393679eda6a590638abda16d167754393f5d0850dcbca2d0c3735cebe2", - "sha256:c05f16701ab2a4ca146d0bca950af254cb7c02f3c01fca8efbbad82d23b3d9d4", - "sha256:c4057c3b511bb8aef605616bd3f1f002a697c7e4da6adf095ca5b84c0fd43595", - "sha256:c4a65310ccb5c9910c47b078ba78e2787cb3878cdded1702ac3d0da71ddc5228", - "sha256:ca0b3a94ac8d3886c9581b9f9de3ce858263865fdaa383fbc31c310b9eac07c9", - "sha256:cc28e90a7cae7fcba2493953cff61da5a52950e78dc2dacfe931a317ee3d8de7", - "sha256:cdf7365063e80899ae3a697def1277c17a7df7ccfc979990a403dfe77bb54d40", - "sha256:d69858c32f09c3e1ce44b617b3ebba1aba030e777000ebdf72b0d8e365d0b2b3", - "sha256:dbead71dbe65f959b7bd8cf91e0e11d5338033eba34c114f69078d59827ee139", - "sha256:dcbe82b35d1ac43b0d84072408330fd3295c2896973112d495e7234f7e3da2e1", - "sha256:dfc91d4720d48e2a709e9c368d5125b4b5899dced34b5400c3837dadc7d6271b", - "sha256:eded5138cc565a9d618e111c6d5c2547bbdd951114eb822f7f6309e04db0fb47", - "sha256:f4324929c2dd917598212bfd554757feca3e5e0fa60da08be11b4aa8b90013c1", - "sha256:fb66215277a230c456f9038d5e2d84778141643207f85336ef8d2a9da26bd7ca" + "sha256:03c95484d53ed8e479cade8628c9cea00fd9d67f5554764a1110e0d5aa2de96e", + "sha256:05ac3d3916023745aa3b3b388e91b9166be1ca02b7c7e41045da6d12985685f0", + "sha256:0943e4c701196b23c240b3d10ed8ecd674f03089198cf503105b474a4f77f21f", + "sha256:1335d4ef59ab85cab66fe73fd7a4e881c298ee7f63ede918b7faa1b27cbe5212", + "sha256:1c680b269d33ec444afe2bdc647c9eb73166fa47a16d9a75ee56a374f4a45f43", + "sha256:227df19441372610b20e05bdb906e1742ec2ad7a66ac8350dcfd29a63014a83b", + "sha256:30b0a09a2014e621b1adf66a4f705f0809358350a757508ee80209b2d8dae219", + "sha256:3722fddb821b6036fd2a3c814f6bd9b57a89dc6337b9924ecd614ebce3271394", + "sha256:446dee5a491b5bc7d8f825d80d9637e7af43f86a331207b9c9610e2f93fee22a", + "sha256:450e39ab1f7694465060a0550b3f6d328d20297bf2e06aa947b97c21e5241fbd", + "sha256:49e3bc615652617d463069f91b867a4458114c5b104e13b7ae6872e5f79d0844", + "sha256:4bbc6d0af24c1575edc79994c20e1b29e6fb3c6a570371306db0993ecf144dc5", + "sha256:5410111d7b6681d4b0d65e0f58a13be588d01b473822483f77f513c7f93bd3b2", + "sha256:55d43d3feb8f19d07e9f01e5b9be4f28801cf7c60d0fa0d279951b18fae1932b", + "sha256:57985ee7e91d6214c837936dc1608f40f330a6b88bb13f5a57ce5257807da143", + "sha256:61272a5aec2b2661f4fa2b37c907ce9701e821b2c1285d5c3ab0207ebd358d38", + "sha256:633a3b31d9d7c9f02d49c4ab4d0a86065c4a6f6adc297d63d272e043472acab5", + "sha256:64c81456d2a050d380786413786b057983892db105516639cb5d3ee3c7fd5148", + "sha256:66680eae4c4e7fc193d91cfc1353ad6d01b4801ae9b5314f17e11ba55e934183", + "sha256:697a35a083c4f834807a6232b3e62c8b280f7a44ad0b759fd4dce748951e70db", + "sha256:6eeb13218c8cf34c61912e9df2de2853f1d009de0e46ea09ccdf3d757896af0a", + "sha256:7275664f84e027dcb1ad5200b8b18373e9c669b2a9ec33d410c40f5ccf4b257e", + "sha256:738dbe3ef909c4b019d69afc19caf6b5ed0e2f1c786b5d6215fbb7539246e4c6", + "sha256:79b9b9e33bd4c517445a62b90ca0cc279b0f1f3970655c3df9e608bc3f91741a", + "sha256:874ce88264b7e655dde4aeaacdc8fd772a7962faadfb41abe63e2a4861abc3dc", + "sha256:95a0cce17f969fb5391762e5719575217bd10ac5a189d1979442ee54456393f3", + "sha256:960db0e31c4e52fa0fc3ecbaea5b2d3b58f379e32a95ae6b0ebeaa25b93dfd34", + "sha256:965a916373382674e323c957d560b953d81d7a8603fbeee26f7b8248638bd48b", + "sha256:9c1c4b53b24a4c06547ce43e5fee6ec4e0d8fe2d597f4647fc033fd205707365", + "sha256:a2debd8ddce948a8c0938c8c93ade191d2f4ba4649a54302a7da905a81f00b56", + "sha256:a6ea7afb5b30b2317e0bee03c8d34c8181bc5a36f2afd4d0952f378972c4efd5", + "sha256:ac3045267e98fe749408eee1593a142e02357c5c99be0802185ef2170086a863", + "sha256:b1ec490e10d2a77c345def52599311849fc063ae0e67cf4f84528073152bb2ba", + "sha256:b6f3d167d13a16ed263b52dbfedff52c962bfd3d270b46b7518365bcc2121eed", + "sha256:bb1f28a137337fdc18384079fa5726810681055b32b92253fa15ae5656e1dddb", + "sha256:bf2fbbce5fe7cd1aa177ea3eab2b8e6a6bc6e8592e4279ed3db2d62e57c0e1b2", + "sha256:c27bc6a28ae95923350ab382c57113abd38f3928af3c80be6f2ba7eb8d8db0b0", + "sha256:c2c116072a8533f2fec435fde4d134610f806bdac20188c7bd2081f3e9e0133f", + "sha256:caff75b425db5ef8e8f23af93c80f072f97b4fb3afd4af44482905c9f588da28", + "sha256:d27456491ca79532d11e507cadca37fb8c9324a3976294f68fb1eff2dc6ced5a", + "sha256:d40f839dddf6a7d77114fe6b8a70218556408c71d4d6e29413bb5f150a692ff7", + "sha256:df25d9271270ba2133cc88ee83c318372bdc0f2cd6f32e7a450809a111efc45c", + "sha256:e060748a04cccf1e0a6f2358dffea9c080b849a4a68c28b1b907f272b5127e9b", + "sha256:e54b63d0a7c6c54a5f5f726bc93a2078111ef060fec4ecbf34c5db800ca3b3a7", + "sha256:ea2977b21f8d5d9b758bb3f344a75e55ca78e3ff85595d248eee813ae23ecdfb", + "sha256:eadc8fd310edb4bdbd333374f2c8fec6794bbbae99b592f448d8214a5e4050c0", + "sha256:f215789fb1667cdc874c1b8af6a84dc939fd802bf293a8334fce185c79cd359b", + "sha256:f710f346e4c44a4e8bdf23daa974faede58f83334289df80bc9cd12fe82573c7", + "sha256:f759503a97a6ace19e55461395ab0d618b5a117e8d0fbb20e70cfd68a47327f2", + "sha256:fb0ee33124db6eaa517d00890fc1a55c3bfe1cf78ba4a8899d71a06f2d6ff5c7", + "sha256:fd502f96bf5ea9a61cbc0b2b5900d0dd68aa0da197179042bdd2be67e51a1e4b" ], "markers": "python_version >= '3.8'", - "version": "==3.10.5" + "version": "==3.10.6" }, "pydantic": { "hashes": [ diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..ee0a888 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,4 @@ +#!/bin/sh +ln -snf /usr/share/zoneinfo/Asia/Seoul /etc/localtime + +pipenv run uvicorn app.main:app --host 0.0.0.0 --port ${PORT} From 4c959efb6726f8fac5d1439ce63601ac52531e5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=80=EB=AF=BC?= <108014449+stopmin@users.noreply.github.com> Date: Mon, 8 Jul 2024 11:36:54 +0900 Subject: [PATCH 2/3] =?UTF-8?q?CICD=20=EA=B5=AC=EC=B6=95=20(#62)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * python version 3.12.4로 업그레이드 * 도커파일 정의 및 pipfile 업데이트 * ECS Deploy 설정 From 8d3d828cbba9f71cd09b872d2571a64886021bfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=80=EB=AF=BC?= <108014449+stopmin@users.noreply.github.com> Date: Mon, 8 Jul 2024 11:38:50 +0900 Subject: [PATCH 3/3] Update deploy-ecs.yml (#63) --- .github/workflows/deploy-ecs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-ecs.yml b/.github/workflows/deploy-ecs.yml index 53268d0..82de88b 100644 --- a/.github/workflows/deploy-ecs.yml +++ b/.github/workflows/deploy-ecs.yml @@ -23,7 +23,7 @@ permissions: jobs: deploy: name: Deploy - runs-on: ubuntu-latest-8-cores + runs-on: ubuntu-latest steps: - name: Post Slack Channel that Build Start