Profile picture

[๋ฐฐํฌ] Github Actions๋กœ Djnago ๋ธ”๋กœ๊ทธ ๋ฐฐํฌ ์ž๋™ํ™”ํ•˜๊ธฐ

JaehyoJJAng2023๋…„ 12์›” 01์ผ

๐Ÿ’ก ๊ฐœ์š”

Waytothem ์ด๋ผ๋Š” Django ๋ฐฑ์—”๋“œ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฐฐํฌ๋œ ๋ธ”๋กœ๊ทธ๊ฐ€ ํ•˜๋‚˜ ์žˆ๋‹ค.

ํ•ด๋‹น ๋ธ”๋กœ๊ทธ์˜ ๊ฒฝ์šฐ Lightsail 5๋‹ฌ๋Ÿฌ Plan ์งœ๋ฆฌ ์ธ์Šคํ„ด์Šค ์œ„์—์„œ ๊ฑฐ์˜ 1๋…„ 6๊ฐœ์›” ๊ฐ„ ์šด์˜ ์ค‘์— ์žˆ๊ณ  ํ•˜๋‚˜์˜ ์ธ์Šคํ„ด์Šค์— ๋„์ปค ์ปดํฌ์ฆˆ๋กœ Nginx + Certbot + DB(Postgresql) + App์ด ๊ธฐ๋™๋œ๋‹ค.

ํ˜„์žฌ ํ•ด๋‹น ๋ธ”๋กœ๊ทธ์˜ ๋ฐฐํฌ ํŒŒ์ดํ”„๋ผ์ธ์€ ์ •๋ง ๋‹จ์ˆœํ•˜๋‹ค.

  1. ๋กœ์ปฌ์—์„œ ์†Œ์Šค์ฝ”๋“œ ์—…๋ฐ์ดํŠธ ํ›„ ๊นƒํ—ˆ๋ธŒ์— ์—…๋กœ๋“œ (git push)
  2. Lightsail ์ธ์Šคํ„ด์Šค์— SSH ์ ‘์† ํ›„ ๋ณ€๊ฒฝ๋œ ์ฝ”๋“œ ์—…๋ฐ์ดํŠธ (git pull)
  3. docker-compose up -d --build (Re-building)

์œ„ ๋‹จ๊ณ„๋กœ ์ง์ ‘ "์ˆ˜๋™"์œผ๋กœ ๊ฐœ๋ฐœ์ž(๋‚˜)๊ฐ€ ์„œ๋น„์Šค๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.

์–ด๋Š ์ˆœ๊ฐ„, ์ด ๊ณผ์ •์ด ๋„ˆ๋ฌด ๊ท€์ฐฎ๊ฒŒ ๋Š๊ปด์ง€๋”๋ผ. ํ•˜์ง€๋งŒ ์•„๋Š” ๊ฑฐ๋ผ๊ณค ์ˆ˜๋™ ๋ฐฐํฌ๋ฐ–์— ํ•  ์ค„ ๋ชฐ๋ผ์„œ ๋ฐฐํฌ ์ž๋™ํ™”์— ๋Œ€ํ•ด ๊ณ„์† ๊ณต๋ถ€ํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค.
Travis CI, Jenkins ๋“ฑ์„ ๊ณต๋ถ€ํ•ด๋ดค๋Š”๋ฐ ๋‚˜ํ•œํ…Œ๋Š” Github Actions ๋งŒํผ ๊ฐ„ํŽธํ•˜๊ณ  ์‰ฌ์šด๊ฒŒ ์—†๋”๋ผ.


ํ•˜์ง€๋งŒ ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์— ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋Š” ์ž‘์„ฑํ•˜์ง€ ์•Š์•˜์–ด์„œ ํ…Œ์ŠคํŠธ ํŒŒ์ดํ”„๋ผ์ธ์„ ์ž‘์„ฑํ•  ์ˆ˜๋Š” ์—†์—ˆ๋‹ค.
1์ธ ๊ฐœ๋ฐœ์ด๊ธฐ๋„ ํ•˜๊ณ  ํ•ด์„œ ์กฐ๊ธˆ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋ฐฐํฌ ์ž๋™ํ™” ํŒŒ์ดํ”„๋ผ์ธ์„ ๋„์ž…ํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

์†Œ์Šค์ฝ”๋“œ ๋ณ€๊ฒฝ์ด ๊ฐ์ง€๋˜๋ฉด ์ž๋™์œผ๋กœ ๋ฐฐํฌํ•˜๋Š” ์‹์œผ๋กœ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•ด๋ณด์ž!

๐Ÿ“• Container Topology

image


๐Ÿ“Œ ๊นƒํ—ˆ๋ธŒ ์†Œ์Šค์ฝ”๋“œ

https://github.com/JaehyoJJAng/Python_Web_Development_2022


๐Ÿ“Œ ์‚ฌ์ „ ์ค€๋น„

1. SSH Key ์ƒ์„ฑ

Github Actions์—์„œ SSH๋กœ Lightsail์— ์ ‘์†ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋กœ์ปฌ์— SSH Key๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.
์ˆœ์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  • 1. ssh-keygen ๋ช…๋ น์–ด๋กœ ๋กœ์ปฌ ~/.ssh ๊ฒฝ๋กœ์— 'github_id_rsa' ๋ผ๋Š” ์ด๋ฆ„์˜ ssh key pair๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  • 2. ์ƒ์„ฑ๋œ ํ‚ค ํŽ˜์–ด ์ค‘ 'github_id_rsa' Private key ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ cat ์ปค๋งจ๋“œ๋กœ ์ฝ์€ ํ›„ ๋ณต์‚ฌํ•˜์—ฌ [https://github.com/JaehyoJJAng/Python_Web_Development_2022] ๋ ˆํฌ์ง€ํ† ๋ฆฌ์˜ secret ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ๋„ฃ์–ด์ค€๋‹ค.

๋จผ์ € ๋กœ์ปฌ์— ssh key๋ฅผ ์ƒ์„ฑํ•˜์ž.

ssh-keygen -t rsa -b 4096 -C "github actions" -f ~/.ssh/github_id_rsa

๐Ÿ”บ authorized_keys

Lightsail ์„œ๋ฒ„์˜ ~/.ssh/authorized_keys ํŒŒ์ผ์— 'github_id_rsa' Private Key ํŒŒ์ผ์˜ ๋‚ด์šฉ์ด ์ถ”๊ฐ€๋˜์–ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.


2. github secret ๋“ฑ๋ก

์ƒ์„ฑ๋œ github_id_rsa.pub ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ ๋ณต์‚ฌํ•œ ํ›„ https://github.com/JaehyoJJAng/Python_Web_Development_2022์˜ Settings - Security - Secrets and variables - Actions๋กœ ์ด๋™ํ•˜์—ฌ 'New repository secret'์„ ํด๋ฆญํ•˜์ž.
image


'SSH_PRIVATE_KEY' ๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ํ‚ค ๋„ค์ž„์„ ์ •ํ•˜๊ณ  'secret' ํ•ญ๋ชฉ์—๋Š” ์œ„์—์„œ ๋ณต์‚ฌํ–ˆ๋˜ 'github_id_rsa' ๊ฐœ์ธ Private key ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ ๋ถ™์—ฌ๋„ฃ๊ธฐ ํ•˜์ž.
image


๊ทธ๋ฆฌ๊ณ  Lightsail ์ธ์Šคํ„ด์Šค์˜ Public IP, SSH๋กœ ์ ‘์†ํ•  Username๋ช…, ๋กœ์ปฌ์˜ SSH known_host ํŒŒ์ผ ๋‚ด์šฉ์„ secret์œผ๋กœ ๋งŒ๋“ค์–ด์ค€ ํ›„ ๊ฐ’์„ ๋„ฃ์–ด์ฃผ์ž.
image


๊ทธ๋ฆฌ๊ณ  github actions์—์„œ Docker hub์— ๋กœ๊ทธ์ธ๋„ ํ•ด์•ผํ•˜๋ฏ€๋กœ docker hub ๋กœ๊ทธ์ธ ๊ด€๋ จ ์ •๋ณด๋„ ์ƒ์„ฑํ•ด์ฃผ์ž.
image


3. Django Allowed hosts

๊ฐ€๋น„์•„ ๋„๋ฉ”์ธ์„ lightsail ์ธ์Šคํ„ด์Šค์— ์—ฐ๊ฒฐํ•˜์˜€์œผ๋ฏ€๋กœ Django ํ”„๋กœ์ ํŠธ์˜ ALLOWED_HOSTS์— ํ•ด๋‹น ๋„๋ฉ”์ธ์„ ์ถ”๊ฐ€ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

vi ./Python_Web_Development_2022/WTT/.env.prod
...
# ํ•ด๋‹น ๋ณ€์ˆ˜์— ๋„๋ฉ”์ธ๋ช… ์ถ”๊ฐ€
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1] 3.x.x.x. waytothem.store www.waytothem.store
...

4. .dockerignore

์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€์— .env ๊ฐ™์€ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ํฌํ•จ๋œ ์ฑ„ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๊ฐ€ Public registry์— ๋ฐฐํฌ ๋˜๋Š” ๊ฒฝ์šฐ ์‹ฌ๊ฐํ•œ ๋ณด์•ˆ ์œ„ํ˜‘์„ ๋‹นํ•  ์ˆ˜ ์žˆ๊ฒŒ๋œ๋‹ค.

๊ทธ๊ฑธ ๋ฐฉ์ง€ํ•˜๊ณ ์ž Dockerfile์ด ์กด์žฌํ•˜๋Š” WTT/ ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด์— .dockerignore๋ฅผ ์ž‘์„ฑํ•  ๊ฒƒ์ด๋‹ค.

vi ./WTT/.dockerignore
.env.prod
.env.dev
.env.prod.db
Dockerfile
django_ํ”„๋กœ์ ํŠธ์ƒ์„ฑ.txt

๐Ÿ“Œ docker compose ์ˆ˜์ •

๊ธฐ์กด docker-compose.yaml์˜ ๊ฒฝ์šฐ ํ”„๋กœ์ ํŠธ ๋‚ด์˜ Dockerfile์„ ์ฐธ์กฐํ•˜์—ฌ ์ด๋ฏธ์ง€๊ฐ€ ๋นŒ๋“œ๋˜๋„๋ก ์„ค์ • ๋˜์–ด์žˆ๋‹ค.

version: '3.2'

services:
  nginx:
    build: ./nginx
    ...

  web:
    build:
      context: ./WTT
      dockerfile: Dockerfile
    ...

  db:
    image: postgres:12.0-alpine
    ...

db ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ œ์™ธํ•œ nginx, web ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ํ˜„์žฌ ํ”„๋กœ์ ํŠธ ๋‚ด์˜ Dockerfile์„ ์ฐธ์กฐํ•˜์—ฌ ์ด๋ฏธ์ง€๋ฅผ ๋นŒ๋“œํ•˜๊ณ  ์žˆ๋‹ค.


์ถ”ํ›„์— Github Actions๋ฅผ ํ†ตํ•ด ์ด๋ฏธ์ง€๋ฅผ ์ž๋™์œผ๋กœ ๋นŒ๋“œ/๋ฐฐํฌํ•˜๊ณ  ๋ฐฐํฌ๋œ ์ด๋ฏธ์ง€๋ฅผ ๋„์ปค ํ—ˆ๋ธŒ์—์„œ ๋ฐ›์•„์˜ฌ ๊ฒƒ์ด๊ธฐ์— ์•„๋ž˜์ฒ˜๋Ÿผ ๋ฏธ๋ฆฌ ์ˆ˜์ •ํ•ด์ฃผ์ž.

version: '3.2'

services:
  nginx:
    image: <YourDockerUserName>/wtt-nginx:latest # ๋„์ปค ํ—ˆ๋ธŒ์— ๋ฐฐํฌ๋œ ์ด๋ฏธ์ง€ ์‚ฌ์šฉ
    ...

  web:
    image: <YourDockerUserName>/wtt-web:latest   # ๋„์ปค ํ—ˆ๋ธŒ์— ๋ฐฐํฌ๋œ ์ด๋ฏธ์ง€ ์‚ฌ์šฉ
    ...

  db:
    image: postgres:12.0-alpine
    ...

๐Ÿ“Œ ๋ฐฐํฌ

๋ฐฐํฌ ์‹œ ์‚ฌ์šฉ๋˜๋Š” ํ”„๋กœ์ ํŠธ๋Š” ๊นƒํ—ˆ๋ธŒ ์†Œ์Šค์ฝ”๋“œ์— ๋งํฌ๋œ ๊นƒํ—ˆ๋ธŒ ์ฃผ์†Œ์— ์—…๋กœ๋“œ ๋˜์–ด์žˆ๋‹ค.


1. workflow

ํ˜„์žฌ ํ”„๋กœ์ ํŠธ ๊ฒฝ๋กœ(~/Python_Web_Development_2022)์— .github/workflows/BlogDeploy.yaml ํŒŒ์ผ์„ ๋งŒ๋“ค์ž.

mkdir -p .github/workflows && touch .github/workflows/BlogDeploy.yaml

2. workflow ์ž‘์„ฑ

BlogDeploy.yaml ํŒŒ์ผ์— ์•„๋ž˜ ๋‚ด์šฉ์„ ๋ถ™์—ฌ๋„ฃ๊ธฐ ํ•˜์ž.

name: BlogDeploy
on:
  push:
    branches:
      - "main"

jobs:
  deploy_job:
    runs-on: ubuntu-22.04
    steps:
      - name: "[Checkout] 1. Checkout repository"
        uses: actions/checkout@v3

      - name: "[Docker Login] 2. Dockerhub Login"
        uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
        with:
          username: ${{ secrets.DOCKER_HUB_USERNAME }} 
          password: ${{ secrets.DOCKER_HUB_PASSWORD }}

      - name: "[Build] 3. nginx image build & push"
        uses: docker/build-push-action@v2
        with:
          context: ./nginx # Dockerfile์ด ์žˆ๋Š” ๋””๋ ‰ํ† ๋ฆฌ ์ง€์ •
          push: true
          tags: |
            <YourDockerUserName>/wtt-nginx:latest
      
      - name: "[Build] 4. WTT image build & push"
        uses: docker/build-push-action@v2
        with:
          context: ./WTT
          push: true
          tags: |
            <YourDockerUserName>/wtt-web:latest

      - name: "[Deploy] 5. Set up SSH"
        run: |
          mkdir -p ~/.ssh/
          echo "${{ secrets.SSH_PRIVATE_KEY }}" | tee -a ~/.ssh/id_rsa
          chmod 600 ~/.ssh/id_rsa
      
      - name: "[Deploy] 6. Set up Known hosts"
        run: |
          echo "${{ secrets.SSH_KNOWN_HOST }}" | tee -a ~/.ssh/known_hosts
          chmod 644 ~/.ssh/known_hosts
      
      - name: "[Deploy] 7. SSH and Deploy"
        run: |
          ssh -i ~/.ssh/id_rsa ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_PUBLIC_IP }}"
          cd Python_Web_Development_2022
          docker-compose -f docker-compose.yml up -d --build
          "

3. workflow ๋ฐฐํฌ

workflow ์ž‘์„ฑ์ด ๋‹ค ๋๋‚ฌ๋‹ค๋ฉด commit & push๋ฅผ ํ•˜์ž.

git add .
git commit -m "Update BlogDeploy Workflow"
git push -u origin main

https://github.com/JaehyoJJAng/Python_Web_Development_2022 ๋ ˆํฌ์ง€ํ† ๋ฆฌ์˜ Actions ํƒญ์œผ๋กœ ์ด๋™ํ•˜์—ฌ workflow๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰๋๋Š”์ง€ ํ™•์ธํ•˜์ž.
image
๋ฐฐํฌ๋Š” ์„ฑ๊ณต์ ์œผ๋กœ ๋œ ๊ฒƒ ๊ฐ™๋‹ค!


์ด๋ฒˆ์—๋Š” ๋Œ€๋ฌธ ํŽ˜์ด์ง€์˜ ํ…์ŠคํŠธ๋ฅผ ์•„๋ž˜์ฒ˜๋Ÿผ ๋ณ€๊ฒฝํ•˜๊ณ  ๋‹ค์‹œ push ํ•ด๋ณด์ž.

$ vi ./WTT/single_pages/templates/landing.html

<section id="body-wrapper">
    <div class="container">
        <div class="row justify-content-between">
            <div class="col-lg-6 text-muted">
                <h1 class="mt-5 text-center text-dark text">IT</br>์ฝ”๋”ฉ ๋ธ”๋กœ๊ทธ</h1>
                <div class="card mt-1">
                    <div class="card-body">
                        <p class="text-center" style="font-size: 150%;">
                            </br>ํŒŒ์ด์ฌ๊ณผ ๋„์ปค</br>๊ทธ๋ฆฌ๊ณ  ๋ฆฌ๋ˆ…์Šค์™€ ์…ธ ์Šคํฌ๋ฆฝํŒ…์—</br>๋งŽ์€ ๊ด€์‹ฌ์ด ์žˆ์Šต๋‹ˆ๋‹ค!
                             </br>
                            <span style="font-size: 80%;">
                                </br>ํ•ด๋‹น ๋ธ”๋กœ๊ทธ๋Š” IT ์‹ค์Šต ๊ด€๋ จํ•˜์—ฌ</br>๋งŽ์€ ๊ธ€์ด ์“ฐ์—ฌ์งˆ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.
                            </span>
                        </p>
                    </div>
                </div>
            </div>
...
</section>
git add .
git commit -m "landing ํŽ˜์ด์ง€ ๋Œ€๋ฌธ ๊ธ€ ์ˆ˜์ •"
git push -u origin main

image
๋ฐฐํฌ๋Š” ์ •์ƒ์ ์œผ๋กœ ๋œ ๊ฒƒ ๊ฐ™๋‹ค.


http://www.waytothem.store๋กœ ์ ‘์†ํ•ด ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ์ ์šฉ ๋๋Š”์ง€ ํ™•์ธํ•˜์ž.
image
์ž˜ ์ ์šฉ๋๋‹ค!


4. HTTPS ์ ์šฉ

๋งˆ์ง€๋ง‰์œผ๋กœ ์„œ๋น„์Šค์— HTTPS๋ฅผ ์ ์šฉํ•ด๋ณด๋„๋ก ํ•˜์ž.
๋ฌด๋ฃŒ SSL ์ธ์ฆ์„œ์ธ Let's Encrypt๋ฅผ ์ด์šฉํ•  ๊ฑฐ๊ณ  ์˜คํ”ˆ ์†Œ์Šค์ธ certbot์„ ์‚ฌ์šฉํ•˜์—ฌ SSL ์ธ์ฆ์„œ๋ฅผ ์ž๋™์œผ๋กœ ๋ฐœ๊ธ‰ ๋ฐ›์„ ๊ฒƒ์ด๋‹ค.


๋จผ์ € Let's Encrypt๋ฅผ nginx + ๋„์ปค ํ™˜๊ฒฝ์—์„œ ์ž๋™์œผ๋กœ ์ธ์ฆ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ์…ธ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋‹ค์šด๋กœ๋“œ ๋ฐ›์•„์•ผ ํ•œ๋‹ค.
(nginx-certbot(github))

curl -L -O https://github.com/wmnnd/nginx-certbot/raw/master/init-letsencrypt.sh

๋‹ค์šด๋กœ๋“œ ๋ฐ›์•˜์œผ๋ฉด init-letsencrypt.sh ๋‚ด์šฉ ์ค‘ ์ผ๋ถ€๋ถ„์„ ์•„๋ž˜์ฒ˜๋Ÿผ ์ˆ˜์ •ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

#!/bin/bash

if ! [ -x "$(command -v docker-compose)" ]; then
  echo 'Error: docker-compose is not installed.' >&2
  exit 1
fi

domains=(waytothem.store www.waytothem.store) # ๋ณธ์ธ ๋„๋ฉ”์ธ ์ฃผ์†Œ ์ž…๋ ฅ
rsa_key_size=4096
data_path="./data/certbot" # ์ธ์ฆ์„œ๋ฅผ ์ €์žฅํ•  ๊ฒฝ๋กœ ๊ธฐ์ž… (ํ•„์ž๋Š” ๊ธฐ๋ณธ ์ž…๋ ฅ๋œ ๊ฒฝ๋กœ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•จ.)
email="๋‚ด ์ด๋ฉ”์ผ ์ฃผ์†Œ ๊ธฐ์ž…"

... // ๊ทธ ์™ธ์— ์„ค์ •์€ ๊ฑด๋“œ๋ฆด๊ฒŒ ์—†์Œ. ๋””ํดํŠธ๋กœ ๋ƒ…๋‘๊ธฐ

๊ธฐ์กด docker-compose.yaml ํŒŒ์ผ์— ์ถ”๊ฐ€ ๋ฐ ์ˆ˜์ •ํ•ด์ค˜์•ผ ํ•  ๊ฒƒ์ด ์žˆ๋‹ค.

version: "3.3"

services:
  nginx:
    image: yshrim12/wtt-nginx:latest
    volumes:
      - type: volume
        source: "static_volume"
        target: "/usr/src/app/_static"
      - type: volume
        source: "media_volume"
        target: "/usr/src/app/_media"
      - "./data/certbot/conf:/etc/letsencrypt"
      - "./data/certbot/www:/var/www/certbot"
    ports:
      - "80:80"
      - "443:443"
    depends_on:
      - "web"
    container_name: nginx
    command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"

  certbot:
    image: certbot/certbot
    restart: always
    volumes:
      - "./data/certbot/conf:/etc/letsencrypt"
      - "./data/certbot/www:/var/www/certbot"
    container_name: certbot
    depends_on:
      - "nginx"
    networks:
      - "web-net"
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"

    # ... My Apps (web, db)...
    web:
      ...
    
    db:
      ...
  1. nginx ์ปจํ…Œ์ด๋„ˆ์— volumes์— certbot ์ธ์ฆ์„œ๊ฐ€ ์ƒ์„ฑ๋  ๊ฒฝ๋กœ๋ฅผ ์žก์•„์ฃผ์—ˆ๋‹ค.
    • volumes์˜ ๊ฒฝ์šฐ init-letsencrypt.sh์—์„œ ์ˆ˜์ •ํ•œ data_path ๊ฒฝ๋กœ์™€ ๋™์ผํ•ด์•ผ ํ•œ๋‹ค.
  2. nginx ์ปจํ…Œ์ด๋„ˆ์— command ์˜ต์…˜์„ ์ถ”๊ฐ€ํ•˜์˜€๋‹ค.
  3. certbot ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์œ„์™€ ๊ฐ™์ด ๋งŒ๋“ค์–ด์ฃผ์—ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ธฐ์กด nginx.conf ํŒŒ์ผ๋„ ์•„๋ž˜์ฒ˜๋Ÿผ ์ˆ˜์ •ํ•ด์ค˜์•ผ ํ•œ๋‹ค.


๊ธฐ์กด nginx.conf ๋‚ด์šฉ

upstream  greedy_jaehyo {
    server web:8000;

}

server {
    listen 80;
    location / {
        proxy_pass http://greedy_jaehyo;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_redirect off;
    }

    location /static/ {
        alias /usr/src/app/_static/;
    }

    location /media/ {
        alias /usr/src/app/_media/;
    }
}

์ˆ˜์ •๋œ nginx.conf ๋‚ด์šฉ

upstream wtt {
    server web:8000;
}

server {
    listen 80;
    server_name waytothem.store;

    location / {
        return 301 https://$host$request_uri;
    }

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
}

server {
    listen 443 ssl;
    server_name waytothem.store;

    location / {
        proxy_pass http://wtt;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_redirect off;
    }

    location /static/ {
        alias /usr/src/app/_static/;
    }

    location /media/ {
        alias /usr/src/app/_media/;
    }

    ssl_certificate /etc/letsencrypt/live/waytothem.store/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/waytothem.store/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}

์ด์ œ ๋ชจ๋“  ์ค€๋น„๊ฐ€ ๋๋‚ฌ๋‹ค.

๋จผ์ € ํ”„๋กœ์ ํŠธ ๊ฒฝ๋กœ์— ์žˆ๋Š” init-letsencrypt.sh ํŒŒ์ผ์— ์‹คํ–‰ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜์ž.

chmod +x ./init-letsencrypt.sh

์ด์ œ sudo ๊ถŒํ•œ์œผ๋กœ ํ•ด๋‹น ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋œ๋‹ค.

sudo bash ./init-letsencrypt.sh

image


[Other Projects] ๐Ÿ’ฅ [Docker] certbot + nginx๋กœ SSL ์ธ์ฆ์„œ ๋ฐœ๊ธ‰ํ•˜๊ธฐ - ๋‚ด๊ฐ€ ๋งŒ๋“  ์‚ฌ์ดํŠธ์— HTTPS ์„ค์ •ํ•˜๊ธฐ


๐Ÿ”บ ๋ณด์•ˆ ์ด์Šˆ

tree -L 2 .
.
โ”œโ”€โ”€ WTT
โ”‚   โ”œโ”€โ”€ Dockerfile
โ”‚   โ”œโ”€โ”€ _media
โ”‚   โ”œโ”€โ”€ _static
โ”‚   โ”œโ”€โ”€ accountapp
โ”‚   โ”œโ”€โ”€ blog
โ”‚   โ”œโ”€โ”€ board
โ”‚   โ”œโ”€โ”€ django_ํ”„๋กœ์ ํŠธ์ƒ์„ฑ.txt
โ”‚   โ”œโ”€โ”€ do_it_django_prj
โ”‚   โ”œโ”€โ”€ manage.py
โ”‚   โ”œโ”€โ”€ profileapp
โ”‚   โ”œโ”€โ”€ requirements.txt
โ”‚   โ”œโ”€โ”€ single_pages
โ”‚   โ”œโ”€โ”€ .env.prod
โ”‚   โ”œโ”€โ”€ .env.prod.db
โ”‚   โ”œโ”€โ”€ .env.dev
โ”‚   โ””โ”€โ”€ templates
โ”œโ”€โ”€ docker-compose.dev.yml
โ”œโ”€โ”€ docker-compose.yml
โ”œโ”€โ”€ migrate.sh
โ”œโ”€โ”€ nginx
โ”‚   โ”œโ”€โ”€ Dockerfile
โ”‚   โ””โ”€โ”€ nginx.conf
โ””โ”€โ”€ venv
    โ”œโ”€โ”€ bin
    โ”œโ”€โ”€ include
    โ”œโ”€โ”€ lib
    โ”œโ”€โ”€ lib64 -> lib
    โ””โ”€โ”€ pyvenv.cfg

16 directories, 10 files

ํ˜„์žฌ ํ”„๋กœ์ ํŠธ ๊ฒฝ๋กœ์ธ WTT/ ๋””๋ ‰ํ† ๋ฆฌ ํ•˜์œ„์— .env ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋“ค์ด ์œ„์น˜ํ•ด์žˆ๋‹ค.


.dockerignore์— ํ•ด๋‹น ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ํŒŒ์ผ๋“ค์„ ๋„ฃ์—ˆ์Œ์—๋„ ์ปจํ…Œ์ด๋„ˆ์— ๋ฐ˜์˜์ด ๋˜๊ธธ๋ž˜ ๋ฌด์Šจ ์ด์œ ์ธ์ง€ ํ™•์ธํ•ด๋ณด๋‹ˆ ์•„๋ž˜ ์ด์œ  ๋•Œ๋ฌธ์ด์—ˆ๋‹ค!

version: '3.2'

services:
  nginx:
    image: yshrim12/wtt-nginx:latest
    
  web:
    image: yshrim12/wtt-web:latest
    ...
    volumes:
      ...
      - type: bind
        source: "./WTT"
        target: "/usr/src/app"
    env_file:
      - "./WTT/.env.prod"
    ...

  db:
    image: postgres:12.0-alpine
    volumes:
      - type: volume
        source: "postgres_data"
        target: "/var/lib/postgresql/data"
    env_file:
      - "./WTT/.env.prod.db"
    container_name: postgresql
...

web ์ปจํ…Œ์ด๋„ˆ์˜ volumes๋ฅผ ํ™•์ธํ•ด๋ณด์ž. bind ๋งตํ•‘์œผ๋กœ ./WTT:/usr/src/app ๊ฒฝ๋กœ๋กœ ๋งˆ์šดํŠธ๊ฐ€ ์žกํ˜€์žˆ๋‹ค.

์•„๋ž˜ ๊ธ€์€ GPT์˜ ๋‹ต๋ณ€์ด๋‹ค.

  • .dockerignore ํŒŒ์ผ์€ Docker ๋นŒ๋“œ ์ปจํ…์ŠคํŠธ ๋‚ด์—์„œ Docker์— ์˜ํ•ด ์‚ฌ์šฉ๋˜๋ฉฐ, ์ด ํŒŒ์ผ์— ๋ช…์‹œ๋œ ํŒจํ„ด์— ๋”ฐ๋ผ ๋นŒ๋“œ ์ปจํ…์ŠคํŠธ์˜ ํŒŒ์ผ๊ณผ ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ Docker ๋นŒ๋“œ ํ”„๋กœ์„ธ์Šค์— ์˜ํ•ด ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค. ์ด ํŒŒ์ผ์€ Docker ๋นŒ๋“œ ๋‹จ๊ณ„์—์„œ๋งŒ ์˜ํ–ฅ์„ ๋ฏธ์น˜๋ฉฐ, ์ด๋ฏธ์ง€๊ฐ€ ์‹คํ–‰ ์ค‘์ธ ์ปจํ…Œ์ด๋„ˆ์—๋Š” ์ ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  • ์ฆ‰, .dockerignore ํŒŒ์ผ์€ Dockerfile์—์„œ COPY ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ˜ธ์ŠคํŠธ ํŒŒ์ผ ์‹œ์Šคํ…œ์—์„œ ์ด๋ฏธ์ง€๋กœ ๋ณต์‚ฌํ•  ๋•Œ๋งŒ ์˜ํ–ฅ์„ ๋ฏธ์นฉ๋‹ˆ๋‹ค. ์ด๋ฏธ์ง€๊ฐ€ ์‹คํ–‰ ์ค‘์ธ ์ปจํ…Œ์ด๋„ˆ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ปจํ…Œ์ด๋„ˆ ๋‚ด์˜ ํŒŒ์ผ ๋ฐ ๋””๋ ‰ํ† ๋ฆฌ ์ ‘๊ทผ ๊ถŒํ•œ ๋ฐ ๊ตฌ์„ฑ์€ ํ•ด๋‹น ์ปจํ…Œ์ด๋„ˆ์˜ ์„ค์ • ๋ฐ ์‹คํ–‰ ํ™˜๊ฒฝ์— ๋”ฐ๋ผ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค.

  • ๋”ฐ๋ผ์„œ .dockerignore ํŒŒ์ผ์— ๋ช…์‹œ๋œ ๋‚ด์šฉ์ด ์ปจํ…Œ์ด๋„ˆ์— ์ ์šฉ๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ปจํ…Œ์ด๋„ˆ์—์„œ ํŠน์ • ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ œ์™ธํ•˜๋ ค๋ฉด Dockerfile์ด๋‚˜ ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰ ๋ช…๋ น์—์„œ ํ•ด๋‹น ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ œ์™ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ์˜ˆ๋ฅผ ๋“ค์–ด, Dockerfile์—์„œ COPY ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ .dockerignore ํŒŒ์ผ์— ๋ช…์‹œ๋œ ํŒŒ์ผ์ด ๋ณต์‚ฌ๋˜์ง€ ์•Š๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” COPY ๋ช…๋ น์–ด์—์„œ ํ•ด๋‹น ํŒŒ์ผ์„ ๋ช…์‹œ์ ์œผ๋กœ ์ œ์™ธํ•˜๊ฑฐ๋‚˜, Dockerfile ๋‚ด์—์„œ ์ด ํŒŒ์ผ๋“ค์„ ์‚ญ์ œํ•˜๋Š” ์ž‘์—…์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ปจํ…Œ์ด๋„ˆ์—์„œ ํŠน์ • ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ œ์™ธํ•˜๋ ค๋ฉด Dockerfile ๋‚ด์—์„œ ์ด์— ๋Œ€ํ•œ ์กฐ์น˜๋ฅผ ์ทจํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. .dockerignore ํŒŒ์ผ์€ Docker ๋นŒ๋“œ ํ”„๋กœ์„ธ์Šค์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์ด๋ฉฐ, ๋นŒ๋“œ ์ปจํ…์ŠคํŠธ ๋‚ด์˜ ํŒŒ์ผ์„ Docker ์ด๋ฏธ์ง€๋กœ ๋ณต์‚ฌํ•  ๋•Œ๋งŒ ํ•ด๋‹น ํŒŒ์ผ์ด ๋ฌด์‹œ๋˜๋„๋ก ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.


๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ./WTT ๋””๋ ‰ํ† ๋ฆฌ ํ•˜์œ„์— ์žˆ๋Š” .env ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ํŒŒ์ผ๋“ค์€ ๋ถ€๋ชจ ๋””๋ ‰ํ† ๋ฆฌ๋กœ ๋นผ๋‚ด์™€์•ผ ํ•œ๋‹ค. ๋นผ๋‚ด์˜ค๊ธฐ ์ „์— .env ๋ผ๋Š” ์ƒˆ๋กœ์šด ํด๋”๋ฅผ ํ”„๋กœ์ ํŠธ ๊ฒฝ๋กœ์— ์ƒ์„ฑํ•˜์ž.

$ pwd
/home/ubuntu/Python_Web_Development_2022

$ mkdir .env

$ mv ./WTT/.env* .env/

๊ทธ๋ฆฌ๊ณ  docker-compose.yaml์—์„œ web ์ปจํ…Œ์ด๋„ˆ์™€ db ์ปจํ…Œ์ด๋„ˆ์˜ env_file ์˜ต์…˜๋„ ์•„๋ž˜์ฒ˜๋Ÿผ ์ˆ˜์ •ํ•˜์ž.

...
  web:
    ...
    env_file:
      - ".env/.env.prod"

  db:
    ...
    env_file:
      - ".env/.env.prod.db"

๐Ÿ”บ ๊ทธ๋Ÿผ ์ด์ œ ์ปจํ…Œ์ด๋„ˆ์— .env ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ํŒŒ์ผ๋“ค์ด ๊ฐ™์ด ์˜ฌ๋ผ๊ฐ€๋Š” ์ผ์€ ์—†์„ ๊ฒƒ์ด๋‹ค!


Loading script...

ยฉ 2025, Built with Gatsby