Django Deploy手順整理(gunicorn/nginx/django)

◾️ Deploy関連手順整理 (参考サイト)

1. python localでweb service開発完了(virtual envでの開発作業)
2. package関連内容export (pip freeze > requirements.txt)
3. 開発ソースgit push
4. VPS (dockerがinstallされた仮想machine準備)
 => docker GUI 操作用portainer container作成・実行
5. Docker file作成
6. Docker Imageファイル作成
7. Docker Container作成 

  • STEP 1 : python localでweb service開発完了
以前作業したpinterest app

  • STEP2 : Generate output suitable for a requirements file

mac conda環境でpip freezeしたらisort / certifiなど不要内容も含まれたので削除

(pinterestEnv) $ pip freeze > requirements.txt
(pinterestEnv) $ cat requirements.txt 
appdirs==1.4.4
asgiref==3.3.1
astroid==2.5.1
autopep8==1.5.5
beautifulsoup4==4.9.3
black==20.8b1
certifi==2020.12.5
click==7.1.2
Django==3.1.7
django-bootstrap4==2.3.1
django-environ==0.4.5
django-mathfilters==1.0.0
isort @ file:///tmp/build/80754af9/isort_1612243941122/work
.....

  • STEP 3 : 開発ソースgit push

git push

  • STEP 4 : VPS (dockerがinstallされた仮想machine準備)

GCP compute engine利用

1. compute engine > vm instance作成 (ubuntu 18.04)
2. docker 関連 package install

$ sudo apt-get update
$ sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
$ sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo apt-key fingerprint 0EBFCD88
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io 
$ docker -v

=> docker GUI 操作用portainer container作成・実行(portainer doc)

docker run -d -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce

url => compute engine instanceのpublic ip:9000

  • STEP 5 : Docker file作成 (.envのSECRET_KEYはテスト用で*開発環境のみ*)

 ※注意:.envファイルのSECRET_KEYは本番には反映しないよう。開発用

FROM python:3.9.2

WORKDIR /home/

RUN git clone https://github.com/cit007/pinterest.git

WORKDIR /home/pinterest/

RUN echo "SECRET_KEY=xxxxx>.env

RUN pip install -r requirements.txt

RUN python manage.py migrate

EXPOSE 80

CMD ["python", "manage.py", "runserver", "0.0.0.0"]

  • STEP 6 : Imageファイル作成

=> Images > uplaod tabから[STEP 5]で作成したDockerfileを選択し imageを作成

  • 作成したpinterest_test_image:1イメージをcontainer実行(vm instance ssh)
$ docker run -d -p 8000:8000 pinterest_test_image:1
49e9fd614c93788a504f1a9f53b2a6c1d691b4e2d2f2e2644a565b5f4bd584aa
$ docker ps -a
CONTAINER ID   IMAGE                    COMMAND                  CREATED              STATUS              PORTS    
                          NAMES
49e9fd614c93   pinterest_test_image:1   "python manage.py ru…"   6 seconds ago        Up 5 seconds        0.0.0.0:8
000->8000/tcp             vigorous_jones
493d0d9891fa   portainer/portainer-ce   "/portainer"             About a minute ago   Up About a minute   8000/tcp,
 0.0.0.0:9000->9000/tcp   portainer
a153e7ee9bd7   nginx                    "/docker-entrypoint.…"   43 hours ago         Up 43 hours         0.0.0.0:8
0->80/tcp                 pinterest_nginx

◾️ 開発用としてPython Web ApplicationをDocker container実行しましたが、

本番ではこのようにデプロイするとNG. djangoを本番リリースし、runserverなどのコマンドを直接使用しないように注意を呼びかけている。(ref site)

=> Gunicorn利用してデプロイするため、requirements.txtファイルにgunicorn dependency追加して新しいイメージ作成し、デプロイする

$  pip install gunicorn
$  pip freeze > requirements.txt
$  git add requirements.txt 
$  git commit -m "gunicorn package"
$  git push origin master
  • Dockerfile再作成してDocker image作成

※ portainer利用でDockerfile uploadし、以前のcacheが影響するので注意


# CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
CMD ["gunicorn", "project-name.wsgi", "--bind", "0.0.0.0:8000"]
  • cssなどが正しく提供されてない問題
$ docker run -d -p 8000:8000 pinterest_gunicorn:1
94b688e9548997c8afbc79ef0aee8db65753e0078b3cae6b82186172c3c5576e
root@pinterest-instance-1:/home/itcho0077# docker ps -a
CONTAINER ID   IMAGE                    COMMAND                  CREATED             STATUS             PORTS      
                        NAMES
94b688e95489   pinterest_gunicorn:1     "gunicorn pragmatic.…"   4 seconds ago       Up 3 seconds       0.0.0.0:800
0->8000/tcp             thirsty_cannon
493d0d9891fa   portainer/portainer-ce   "/portainer"             About an hour ago   Up About an hour   8000/tcp, 0
.0.0.0:9000->9000/tcp   portainer
a153e7ee9bd7   nginx                    "/docker-entrypoint.…"   44 hours ago        Up 44 hours        0.0.0.0:80-
>80/tcp                 pinterest_nginx

◾️ DockerでpythonアプリをNGINXとGUNICORNで起動

NGINX container <-------GUNICORN------->Django container

1. request http://xxx.xxx.xxx.xxx:80 
2. route request http://pinterest_gunicorn:8000 -> Django container
    (NGINX containerとDjango containerは同じDocker networkにする)

  • Docker network作成

◾️ pinterest_gunincorn:1 イメージを利用してdocker network選択しdjango_container作成

  • GUNICORN 設定ファイル作成(site)
  • 作成したnginx.conf ファイルをvm instance upload

-> nginx container経由でdjango container接続成功


◾️ staticfiles(python manage.py collectstatic)作成・NGINXとの連携手順

RUN python manage.py migrate

RUN python manage.py collectstatic

EXPOSE 8000

# CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
CMD ["gunicorn", "pragmatic.wsgi", "--bind", "0.0.0.0:8000"]

-> Dockerfileに collectstatic実行のイメージ(pinterest_gunicorn:2)作成

  • static file対応のため既存container削除
root@pinterest-instance-1:/home/itcho0077# docker ps
CONTAINER ID   IMAGE                    COMMAND                  CREATED      STATUS      PORTS                              NAMES
d33d8a264522   nginx:latest             "/docker-entrypoint.…"   2 days ago   Up 2 days   0.0.0.0:80->80/tcp                 nginx_container
b163ad821764   pinterest_gunicorn:1     "gunicorn pragmatic.…"   2 days ago   Up 2 days   8000/tcp                           django_container
493d0d9891fa   portainer/portainer-ce   "/portainer"             3 days ago   Up 3 days   8000/tcp, 0.0.0.0:9000->9000/tcp   portainer
root@pinterest-instance-1:/home/itcho0077# docker stop d33d8a264522 b163ad821764
d33d8a264522
b163ad821764
root@pinterest-instance-1:/home/itcho0077# docker rm d33d8a264522 b163ad821764
d33d8a264522
b163ad821764

  • create static volume (static / media)
  • create djnago container (同じnetwork設定)
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
  • create nginx-container (同じnetwork選択)
root@pinterest-instance-1:/home/itcho0077# cat nginx.conf
worker_processes auto;
events {
}
http {
  server {
    listen 80;
    include mime.types;
    location /static/ {
        alias /data/static/;
    }
    location /media/ {
        alias /data/media/;
    }
    
    location / {
        proxy_pass http://django_container:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
  }
}

◾️ mariadb container(using named volume)利用して環境構築する方法

  1. named volume作成(dbData)後、mariadb container作成

2. 次のDockerfileを利用してdjango_container用image(pinterest_gunicorn:3)作成

FROM python:3.9.2

WORKDIR /home/

RUN git clone https://github.com/cit007/pinterest.git

WORKDIR /home/pinterest/

RUN pip install -r requirements.txt

RUN pip install gunicorn

RUN pip install mysqlclient

RUN echo "SECRET_KEY=xxx" > .env

# RUN python manage.py migrate

RUN python manage.py collectstatic

EXPOSE 8000

# CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
# CMD ["gunicorn", "pragmatic.wsgi", "--bind", "0.0.0.0:8000"]
CMD ["bash", "-c", "python manage.py migrate --settings=pragmatic.settings.prod && gunicorn pragmatic.wsgi --env DJANGO_SETTINGS_MODULE=pragmatic.settings.prod --bind 0.0.0.0:8000"]

–settings=pragmatic.settings.prod

gunicorn pragmatic.wsgi –env DJANGO_SETTINGS_MODULE=pragmatic.settings.prod

3. develop/production deploy用ファイル構成

  • 修正前:pragmatic > settings.py
  • 修正後:pragmatic > setting > base.py(既存settings.pyの元) | dev.py | prod.py

DEPLOYし、dev.py とprod.pyそれぞれのDATABASESなどを設定

containerそれぞれ設定が毎回複雑で面倒です。各containerをdocker swarmを利用してservice化し、問題発生し自動起動するようにしましょう

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です