본문 바로가기
프로그래밍

[docker] 도커 컨테이너 연결을 통한 프로젝트 구성(feat. nginx, django, postgresql)

by choihyuunmin 2024. 5. 25.
728x90

 

도커 컨테이너를 이용한 django 프로젝트 생성에 대해 알아보겠습니다.

django 컨테이너에 nginx, postgresql 컨테이너를 연결하여 웹, was, db의 3tier(3계층) 구조를 구현해보고자 합니다.

이번에도 "한 권으로 배우는 도커 & 쿠버네티스" 책을 바탕으로 공부한 내용을 정리합니다.(https://product.kyobobook.co.kr/detail/S000213057687)

1. django 프로젝트 생성

이번 포스팅에서는 DockerFile을 이용해서 컨테이너를 실행해보겠습니다.

django프로젝트를 생성하기 위해 먼저 파이썬 가상환경을 통해 django를 설치하겠습니다.

 

먼저 파이썬 버전을 확인합니다.

> python -V
Python 3.11.7

 

제가 사용하고 있는 파이썬의 버전은 3.11입니다.

이제 가상환경을 생성한 뒤, django 프레임워크를 설치하겠습니다.

 

> python -m venv django-docker
> source django-docker/bin/activate
> pip install django gunicorn psycopg2-binary
Collecting django
  Obtaining dependency information for django from https://files.pythonhosted.org/packages/1d/23/02f3795a71196019bcfec4c67890a6369e43b023474154fa0b2b7060346d/Django-5.0.6-py3-none-any.whl.metadata
  Downloading Django-5.0.6-py3-none-any.whl.metadata (4.1 kB)
Collecting gunicorn
  Obtaining dependency information for gunicorn from https://files.pythonhosted.org/packages/29/97/6d610ae77b5633d24b69c2ff1ac3044e0e565ecbd1ec188f02c45073054c/gunicorn-22.0.0-py3-none-any.whl.metadata
  Downloading gunicorn-22.0.0-py3-none-any.whl.metadata (4.4 kB)
Collecting psycopg2-binary
  Obtaining dependency information for psycopg2-binary from https://files.pythonhosted.org/packages/7a/1f/a6cf0cdf944253f7c45d90fbc876cc8bed5cc9942349306245715c0d88d6/psycopg2_binary-2.9.9-cp311-cp311-macosx_11_0_arm64.whl.metadata
  Downloading psycopg2_binary-2.9.9-cp311-cp311-macosx_11_0_arm64.whl.metadata (4.4 kB)
Collecting asgiref<4,>=3.7.0 (from django)
  Obtaining dependency information for asgiref<4,>=3.7.0 from https://files.pythonhosted.org/packages/39/e3/893e8757be2612e6c266d9bb58ad2e3651524b5b40cf56761e985a28b13e/asgiref-3.8.1-py3-none-any.whl.metadata
  Downloading asgiref-3.8.1-py3-none-any.whl.metadata (9.3 kB)
Collecting sqlparse>=0.3.1 (from django)
  Obtaining dependency information for sqlparse>=0.3.1 from https://files.pythonhosted.org/packages/43/5d/a0fdd88fd486b39ae1fd1a75ff75b4e29a0df96c0304d462fd407b82efe0/sqlparse-0.5.0-py3-none-any.whl.metadata
  Downloading sqlparse-0.5.0-py3-none-any.whl.metadata (3.9 kB)
Collecting packaging (from gunicorn)
  Obtaining dependency information for packaging from https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl.metadata
  Downloading packaging-24.0-py3-none-any.whl.metadata (3.2 kB)
Downloading Django-5.0.6-py3-none-any.whl (8.2 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.2/8.2 MB 21.6 MB/s eta 0:00:00
Downloading gunicorn-22.0.0-py3-none-any.whl (84 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 84.4/84.4 kB 8.7 MB/s eta 0:00:00
Downloading psycopg2_binary-2.9.9-cp311-cp311-macosx_11_0_arm64.whl (2.6 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.6/2.6 MB 34.9 MB/s eta 0:00:00
Downloading asgiref-3.8.1-py3-none-any.whl (23 kB)
Downloading sqlparse-0.5.0-py3-none-any.whl (43 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 44.0/44.0 kB 5.1 MB/s eta 0:00:00
Downloading packaging-24.0-py3-none-any.whl (53 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 53.5/53.5 kB 7.9 MB/s eta 0:00:00
Installing collected packages: sqlparse, psycopg2-binary, packaging, asgiref, gunicorn, django
Successfully installed asgiref-3.8.1 django-5.0.6 gunicorn-22.0.0 packaging-24.0 psycopg2-binary-2.9.9 sqlparse-0.5.0

[notice] A new release of pip is available: 23.2.1 -> 24.0
[notice] To update, run: pip install --upgrade pip

 

설치가 완료되었습니다. gunicorn은 nginx와 통신하기 위해 설치했고, psycopg2는 postgresql 데이터베이스를 다루기 위해 설치했습니다.

django가 설치되었으니, 프로젝트를 실행시켜보겠습니다.

 

> cd django-docker
> mkdir app && cd app
> mkdir back && cd back
> django-admin startproject myapp
> tree
.
└── myapp
    ├── manage.py
    └── myapp
        ├── __init__.py
        ├── asgi.py
        ├── settings.py
        ├── urls.py
        └── wsgi.py

 

django-admin 명령어를 통해 프로젝트를 생성하면 위와 같은 폴더 구조가 생성됩니다.

myapp 디렉터리 안의 settings.py를 수정해서 외부에서 접근이 가능하도록 설정해보겠습니다.

 

> cd myapp/myapp
> vi settings.py

ALLOWED_HOSTS = ['*']

> cd ..
> python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK

 

설정을 변경하고, migrate 명령어를 통해 데이터베이스 변경사항을 적용합니다.

> python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
May 28, 2024 - 11:09:18
Django version 5.0.6, using settings 'myapp.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

 

그다음 runserver 명령어를 통해 서버를 실행시킵니다. 터미널에 나타난 주소로 접속을 해보면 방금 생성한 django 프로젝트에 접속할 수 있습니다.

 

 

서버를 종료하려면, 터미널에서 컨트롤 + c 키를 통해 빠져나올 수 있습니다.

 

방금 실행한 장고 프로젝트를 도커 컨테이너로 만들기 위해 우선 설치에 필요한 라이브러리 명세를 담은 파일인 requirements.txt 파일을 생성하고, 도커 이미지 파일을 생성하기 위한 명령어의 모음인 Dockerfile을 생성하겠습니다.

 

> pip freeze > requirements.txt
> cat requirements.txt
asgiref==3.8.1
Django==5.0.6
gunicorn==22.0.0
packaging==24.0
psycopg2-binary==2.9.9
sqlparse==0.5.0

> vi Dockerfile

 

FROM python:3.11.7

WORKDIR /usr/src/app

COPY . .

RUN python -m pip install --upgrade pip
RUN pip install -r requirements.txt

WORKDIR .


CMD python manage.py runserver 0.0.0.0:8000
EXPOSE 8000

 

하나씩 살펴보겠습니다.

1) FROM : 베이스 이미지를 의미합니다. 이미지 파일의 베이스가 python 3.11.7 버전임을 의미합니다.

2) WORKDIR : cd 명령어와 비슷합니다. 컨테이너 내부의 /usr/src/app 디렉터리로 이동하겠다는 의미입니다.

3) RUN : 이미지 내부에서 실행할 명령어입니다.

4) COPY : 컨테이너 외부에서 컨테이너 내부로 파일을 복사합니다.

 

※ RUN 과 CMD의 차이는 RUN의 경우에는 이미지 빌드 시 실행되는 명령어, CMD는 컨테이너 실행 시 전달되는 명령어입니다.

※ working 디렉터리를 작성할 때 경로에 주의해주세요. CMD에서 manage.py를 실행하고 있으니 같은 경로에 있어야합니다.

 

이제 requirements.txt 파일과 Dockerfile이 준비되었으니 빌드를 진행하겠습니다.

> docker image build . -t myweb01
[+] Building 24.8s (12/12) FINISHED                                                                                                             docker:desktop-linux
 => [internal] load build definition from Dockerfile                                                                                                            0.0s
 => => transferring dockerfile: 242B                                                                                                                            0.0s
 => [internal] load .dockerignore                                                                                                                               0.0s
 => => transferring context: 2B                                                                                                                                 0.0s
 => [internal] load metadata for docker.io/library/python:3.11.7                                                                                                3.4s
 => [auth] library/python:pull token for registry-1.docker.io                                                                                                   0.0s
 => [1/6] FROM docker.io/library/python:3.11.7@sha256:63bec515ae23ef6b4563d29e547e81c15d80bf41eff5969cb43d034d333b63b8                                         16.3s
 => => resolve docker.io/library/python:3.11.7@sha256:63bec515ae23ef6b4563d29e547e81c15d80bf41eff5969cb43d034d333b63b8                                          0.0s
 ...
 => [internal] load build context                                                                                                                               0.0s
 => => transferring context: 142.34kB                                                                                                                           0.0s
 => [2/6] WORKDIR /usr/src/app                                                                                                                                  0.1s
 => [3/6] COPY . .                                                                                                                                              0.0s
 => [4/6] RUN python -m pip install --upgrade pip                                                                                                               2.2s
 => [5/6] RUN pip install -r requirements.txt                                                                                                                   2.4s
 => [6/6] WORKDIR ./myapp                                                                                                                                       0.0s
 => exporting to image                                                                                                                                          0.3s
 => => exporting layers                                                                                                                                         0.3s
 => => writing image sha256:69eb944c635b2d47e14b9f39455cccbad21e3bfd776a17a5bb7609daa9429a1b                                                                    0.0s
 => => naming to docker.io/library/myweb01
 
 > docker images
 REPOSITORY                                                TAG                                                                          IMAGE ID       CREATED          SIZE
myweb01                                                   latest                                                                       69eb944c635b   34 seconds ago   1.09GB

 

이미지가 생성되었습니다.

 

> docker container run -d -p 8000:8000 myweb01
999d7297514b97686d4509154dd37567cd69f19fef2b7e692eaaa8a93806f7c6

컨테이너를 실행시키고 (d 옵션은 백그라운드 실행, p 옵션은 포트포워딩) 브라우저를 통해 8000번 포트로 접속하면 아까와 같은 장고 화면이 나타납니다.

 

 

 

2. nginx 이미지 pull 및 컨테이너 실행

다음은 nginx를 실행시키고, 위에서 띄워놓은 장고 프로젝트와 연결시키겠습니다.

 

> cd django-docker
> cd app
> mkdir front

처음에 생성한 django-docker 프로젝트 안에 front라는 디렉터리를 만들어두겠습니다.

 

nginx와 django를 연결하기 위해서는 gunicorn이 필요합니다. 위에서 파이썬 패키지를 설치할 때 gunicorn을 같이 설치했는데, nginx에서 들어오는 요청을 gunicorn에서 처리해서 django로 보내주게됩니다.

 

도식화하면

+----------------+        +----------------+        +----------------+
|                |        |                |        |                |
|     Nginx      +------->+   Gunicorn     +------->+    Django      |
|                |        |                |        |                |
+----------------+        +----------------+        +----------------+

이런 모양이 되는 구조입니다.

 

nginx와 gunicorn을 연결하기 위해 nginx에서 사용하는 default.conf를 작성해보겠습니다. 

upstream myweb{
    server django:8000'
}

server{
    listen 80;
    server_name localhost;
    location /{
        proxy_pass http://myweb;
    }
}

 

80번 포트로 받은 요청을 myweb이라는 프록시를 설정해서 django:8000 주소로 요청을 리다이렉트 시키는 내용입니다.

이제 Dockerfile을 만들어서 이미지를 빌드해보겠습니다.

 

FROM nginx:1.25.3


RUN rm /etc/nginx/conf.d/default.conf
COPY default.conf /etc/nginx/conf.d/
CMD ["nginx", "-g", "daemon off;"]

 

이미지 내부에 있는 default.conf를 삭제하고 방금 생성한 파일을 복사하는 명령어가 추가됐습니다.

CMD의 대괄호의 의미는 대괄호 안에 있는 명령어를 모두 문자열 형식으로 받아서 명령을 내린다는 것을 의미합니다. 명령어에 특수문자가 있거나 다른 문자열이 포함된 경우 정확한 결과가 나오지 않을 수 있으니 대괄호로 감싸서 작성해줍니다.

 

Dockerfile을 이미지로 빌드만 해놓고 컨테이너는 아직 실행시키지 않습니다. nginx config파일에 upstream으로 지정해둔 django:8000 서버를 찾을 수 없기 때문에 에러가 발생할 것입니다.

 

이제 아까 만들어둔 django의 dockerfile을 수정하겠습니다. 기존에 python 명령어로 실행하던 서버를 gunicorn으로 실행시키도록 변경합니다.

FROM python:3.11.7

WORKDIR /usr/src/app

COPY . .

RUN python -m pip install --upgrade pip
RUN pip install -r requirements.txt

WORKDIR .

CMD gunicorn --bind 0.0.0.0:8000 myapp.wsgi:application

EXPOSE 8000

다시 빌드를 진행하고 서로 통신을 위해 docker network를 생성해줍니다.

 

> docker network create mynetwork
> docker network ls
NETWORK ID     NAME                     DRIVER    SCOPE
1636aa174c3d   airflow-docker_default   bridge    local
bd176f2236c8   bridge                   bridge    local
1c88b2134b99   host                     host      local
1082fa4218ae   mynetwork                bridge    local
8284623a46b9   none                     null      local

 

이제 컨테이너를 실행하겠습니다. 먼저 django부터 실행시켜줍니다.

 

> docker container run -d --name django --network mynetwork myweb
645755a09e9a14be9b26008124a0a751bd3f54623d88f185aad37107643f1bae

위에서 생성한 네트워크를 부여합니다. 처음에 실행했던 django 컨테이너 실행구문과 다른 것을 볼 수 있는데, 포트번호가 사라졌습니다.

nginx를 통해서 접속이 되기 때문에 포트포워딩을 해제했습니다.

nginx도 같은 방식으로 실행시킵니다.

 

> docker container run -d --name nginx --network mynetwork -p 80:80 mynginx
c9ffe375466403e65ec1dc0482add0c147d0444353f3c12e43350dd74cf6faf1

nginx는 포트포워딩을 설정해줍니다.

 

컨테이너를 실행시켜주면, 위와 같이 포트번호 없이(http 기본 포트 80번) django에 접속이 되는 것을 확인할 수 있습니다.

docker desktop에서 컨테이너 로그를 확인하면

위와 같이 접속한 로그가 찍히는 것을 확인할 수 있습니다.

이제 마지막으로 데이터베이스와 연동을 진행해보겠습니다.

 

3. postgresql 이미지 pull 및 컨테이너 실행

우선 postgresql 이미지를 pull해서 받아오겠습니다. 데이터베이스의 경우 설정할 게 많지 않아 Dockerfile보다는 이미지를 직접 pull해오거나, 로컬에 구축하여 많이 사용합니다.

저는 지난번에 가져온 이미지가 있어 그대로 사용하겠습니다.

 

두번째로, django와 postgresql을 연결해야 하니 django 프로젝트에 데이터베이스 관련 설정을 추가해줍니다.

접속 주소 관련해서 수정했던 settings.py 를 다시 열어줍니다.

 

> vi settings.py
#DATABASES = {
#    "default": {
#        "ENGINE": "django.db.backends.sqlite3",
#        "NAME": BASE_DIR / "db.sqlite3",
#    }
#}

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "NAME": "postgres",
        "USER": "postgres",
        "PASSWORD": "1234",
        "HOST": "postgresql",
        "PORT": 5432
    }
}

 

기존에 설정되어 있는 데이터베이스를 주석처리하고 밑에 postgresql 관련 접속정보를 작성합니다.

다시 django 이미지를 빌드합니다.

 

이제 postgresql 컨테이너를 실행하겠습니다. 컨테이너 실행시 접속정보를 위에 django settings.py에 적은 접속정보와 일치하게 실행시켜야합니다. 네트워크도 위에서 설정한 nginx와 django가 사용하는 mynetwork에 바인딩시켜줍니다.

 

> docker container run --name postgresql --network mynetwork \
> -e POSTGRES_PASSWORD=1234 \
> --mount type=volume,source=myvolume,target=/var/lib/postgresql/data \
> -d postgres
134279e127acfcdf099e380e0aec8496298b1822971514bd1becf550bc27528f

volume과 network를 설정하고 컨테이너를 실행합니다. volume 관련 설명은 지난 포스트에서 다루었습니다.

https://choihyuunmin.tistory.com/116

 

[docker] 도커 기초 명령어

도커를 사용하기 위한 기본 명령어와 작동 방식에 대해 알아보겠습니다.mac 환경에 docker desktop을 통해 도커를 설치했습니다.1. 도커 작동 방식1-1. 도커의 구조먼저 도커는 크게 세 가지로 구성됩

choihyuunmin.tistory.com

 

 

다시 django 컨테이너를 실행시킨 뒤에 브라우저로 접속해봅니다. 데이터베이스가 제대로 연결되어 있으면 오류 없이 화면이 잘 나오는 것을 확인할 수 있습니다.

 

django 컨테이너 내부로 이동해서 데이터베이스가 잘 연결되어 있는지 확인하겠습니다.

 

> docker exec -it c35dfc6f2595c /bin/bash
root@c35dfc6f2595:/usr/src/app# python manage.py inspectdb
# This is an auto-generated Django model module.
# You'll have to do the following manually to clean this up:
#   * Rearrange models' order
#   * Make sure each model has one field with primary_key=True
#   * Make sure each ForeignKey and OneToOneField has `on_delete` set to the desired behavior
#   * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table
# Feel free to rename the models, but don't rename db_table values or field names.
from django.db import models
root@c35dfc6f2595:/usr/src/app# python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK

 

6. 도커 컴포즈(docker-compose)

지금까지 django와 nginx, postgresql까지 이미지로 만들어서 컨테이너끼리 연결시키는 실습을 해보았습니다.

컨테이너를 따로따로 관리하다보니 실행시키고, 종료시키는 과정들이 굉장히 번거로웠는데, 이를 쉽게 관리할 수 있게 해주는 도커 컴포즈라는 프로그램이 있습니다. 

 

도커 컴포즈(docker-compose)는 도커를 활용해서 다수의 컨테이너를 쉽게 관리하고 실행시켜주는 YAML 형식의 파일을 이용한 프로그램입니다. 컨테이너 한두개 정도는 그냥 이미지를 받아와서 dockerfile만들어서 실행시켜주면 되지만 컨테이너 수가 점점 많아지면 관리해야 할 포인트가 많아져 불편해지는데 도커 컴포즈를 이용해서 손쉽게 배포할 수 있습니다.

 

 

앞서 만들었던 컨테이너와 이미지들을 먼저 삭제하고 docker-compose를 통해 컨테이너를 새로 시작해보겠습니다.

> docker container stop
> docker container rm 
> docker image rm

 

그다음 postgresql의 Dockerfile을 작성합니다.

docker-compose에 작성되는 애플리케이션은 모두 Dockerfile을 참고해서 빌드됩니다.

 

FROM postgres:15.4

 

그다음 docker-compose.yml 파일을 작성해보겠습니다.

 

version: "3"

services:
  django:
    build: ./back
    networks:
      - mynetwork1
    depends_on:
      - postgresql
    restart: always

  nginx:
    build: ./front
    networks:
      - mynetwork1
    ports:
      - "80:80"
    depends_on:
      - django
    restart: always

  postgresql:
    build: ./database
    networks:
      - mynetwork1
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: 1234
      POSTGRES_DB: postgres
    volumes:
      - myvolume1:/var/lib/postgresql/data
    restart: always


networks:
  mynetwork1:

volumes:
  myvolume1:

 

build에 작성되는 내용은 애플리케이션의 Dockerfile이 위치하는 디렉터리 경로입니다.

volume과 network는 밑에서 정의한 그대로 넣어주면 됩니다.

restart: always의 의미는 컨테이너가 정지되면 자동으로 재시작하라는 명령입니다.

마지막으로 depends_on의 의미는 컨테이너 실행 순서를 의미합니다. django에 정의된 depends_on에 postgresql이 작성되어 있으니 postgresql 컨테이너가 실행된 후에 django가 실행됨을 의미합니다.

 

docker-compose.yaml 파일을 작성한 후 명령어를 통해 빌드를 진행합니다.

 

> docker compose up -d --build
[+] Building 10.4s (8/8) FINISHED
 => [postgresql internal] load build definition from Dockerfile                                                                                                 0.0s
 => => transferring dockerfile: 57B                                                                                                                             0.0s
 => [postgresql internal] load .dockerignore                                                                                                                    0.0s
 => => transferring context: 2B                                                                                                                                 0.0s
 => [postgresql internal] load metadata for docker.io/library/postgres:15.4                                                                                     3.4s
 => [postgresql auth] library/postgres:pull token for registry-1.docker.io                                                                                      0.0s
 => [postgresql 1/1] FROM docker.io/library/postgres:15.4@sha256:d1168ad5397bf9c94cc417c530469805a8767ed585481d93f174461ac8557e3a                               6.8s
 => => resolve docker.io/library/postgres:15.4@sha256:d1168ad5397bf9c94cc417c530469805a8767ed585481d93f174461ac8557e3a                                          0.0s
 => => sha256:31ce7ceb6d443e2ab4ae91695fea10e1443417fd94c40a46994d5a96940ea1ca 29.18MB / 29.18MB                                                                1.4s
 => => sha256:be24e278ddaad2d55a37b4bdbc7eb73194fceeafedcd70c268bafc55c385b8db 4.38MB / 4.38MB                                                                  0.5s
 => => sha256:d1168ad5397bf9c94cc417c530469805a8767ed585481d93f174461ac8557e3a 7.58kB / 7.58kB                                                                  0.0s
 => => sha256:4b0ef29f7d674302b6a8440975b84e30343bf530b93be0cf8dd0e0a8c7952ac8 9.79kB / 9.79kB                                                                  0.0s
 => => sha256:2644ee0638629a3be17a1dd440788b761eaef1a33da075df53d9d1c753938bce 3.13kB / 3.13kB                                                                  0.0s
 => => sha256:28caef79f6eda62a2701ef8a65f2b7d831768c16d8a68e9b1f9d9cdf425bd7d1 1.17kB / 1.17kB                                                                  0.3s
 => => sha256:dfdbb4d6f9a3bcfc8a4be67d1377969401d918889680a7c6b03049ea8699c9cd 1.38MB / 1.38MB                                                                  0.7s
 => => sha256:ebb06cfd45ecccc5e0239a087529125b8341766a2b42155b493d2a46ac62647c 8.07MB / 8.07MB                                                                  1.4s
 => => sha256:9738a56db3f94a601e623ff2ab30b771a53c00fbba904218f19fae742a30eba8 1.11MB / 1.11MB                                                                  1.2s
 => => sha256:87cb08d2765cc07029f40344159144191287e4517518a2d578d765bfe0b268f0 116B / 116B                                                                      1.5s
 => => sha256:d99960ffd545e8c2574f78896a028a84c1c70e91e2e475589403b80d2ece6d75 3.14kB / 3.14kB                                                                  1.6s
 => => extracting sha256:31ce7ceb6d443e2ab4ae91695fea10e1443417fd94c40a46994d5a96940ea1ca                                                                       1.1s
 => => sha256:f24c03b85fa0a46a815b30dcf4ab5f484eacaeb9d0a1267abc131d2303b0afca 102.38MB / 102.38MB                                                              4.8s
 => => sha256:df24783c0dbbb96ea46f7e46498d25c7eb2672386c9a905b2075ff40886c5456 9.78kB / 9.78kB                                                                  1.8s
 => => sha256:fe8e668d3844850702f52be233da704db303de0b33fa114b58f8ef4df1d0a2d7 129B / 129B                                                                      1.9s
 => => sha256:f06cc9fdee71079549420e795bb68b9a403bde6847fb252ef14732fca889f416 170B / 170B                                                                      2.1s
 => => sha256:47d642a348af4ae60a8fef3213bb374c6b8f5c5e583e6c4cb6f14277cdc3fd0c 4.79kB / 4.79kB                                                                  2.2s
 => => extracting sha256:28caef79f6eda62a2701ef8a65f2b7d831768c16d8a68e9b1f9d9cdf425bd7d1                                                                       0.0s
 => => extracting sha256:be24e278ddaad2d55a37b4bdbc7eb73194fceeafedcd70c268bafc55c385b8db                                                                       0.1s
 => => extracting sha256:dfdbb4d6f9a3bcfc8a4be67d1377969401d918889680a7c6b03049ea8699c9cd                                                                       0.0s
 => => extracting sha256:ebb06cfd45ecccc5e0239a087529125b8341766a2b42155b493d2a46ac62647c                                                                       0.2s
 => => extracting sha256:9738a56db3f94a601e623ff2ab30b771a53c00fbba904218f19fae742a30eba8                                                                       0.0s
 => => extracting sha256:87cb08d2765cc07029f40344159144191287e4517518a2d578d765bfe0b268f0                                                                       0.0s
 => => extracting sha256:d99960ffd545e8c2574f78896a028a84c1c70e91e2e475589403b80d2ece6d75                                                                       0.0s
 => => extracting sha256:f24c03b85fa0a46a815b30dcf4ab5f484eacaeb9d0a1267abc131d2303b0afca                                                                       1.9s
 => => extracting sha256:df24783c0dbbb96ea46f7e46498d25c7eb2672386c9a905b2075ff40886c5456                                                                       0.0s
 => => extracting sha256:fe8e668d3844850702f52be233da704db303de0b33fa114b58f8ef4df1d0a2d7                                                                       0.0s
 => => extracting sha256:f06cc9fdee71079549420e795bb68b9a403bde6847fb252ef14732fca889f416                                                                       0.0s
 => => extracting sha256:47d642a348af4ae60a8fef3213bb374c6b8f5c5e583e6c4cb6f14277cdc3fd0c                                                                       0.0s
 => [postgresql] exporting to image                                                                                                                             0.0s
 => => exporting layers                                                                                                                                         0.0s
 => => writing image sha256:259b8c2f9c839e255c3c45978d5d985ce4a0aab8588e38aaf70cfb7d53be3e11                                                                    0.0s
 => => naming to docker.io/library/app-postgresql                                                                                                               0.0s
 => [django internal] load .dockerignore                                                                                                                        0.0s
 => => transferring context: 2B                                                                                                                                 0.0s
 => [django internal] load build definition from Dockerfile                                                                                                     0.0s
 => => transferring dockerfile: 2B                                                                                                                              0.0s
 ✔ Network app_mynetwork1      Created                                                                                                                          0.0s
 ✔ Volume "app_myvolume1"      Created                                                                                                                          0.0s
 ✔ Container app-postgresql-1  Started                                                                                                                          0.2s
 ✔ Container app-django-1      Started                                                                                                                          0.3s
 ✔ Container app-nginx-1       Started                                                                                                                          0.5s

 

성공적으로 빌드가 됐습니다.

도커 데스크탑에서 확인해보면,

app 이라는 이름으로 묶여서 컨테이너가 실행되고 있음을 확인할 수 있습니다.

 

이상으로 docker를 활용해서 nginx, django, postgresql 애플리케이션을 연결해보는 실습을 마치겠습니다.