Docker 활용한 django 예제

Page content

개요

  • Docker에서 django 개발환경 만들기
  • 간단한 웹개발 실습

참고자료

실습사전조건

  • 가상환경으로 Ubuntu 24.04 LTS
  • make : 소스코드를 컴파일할 때 사용하는 자동 빌드 도구이다.
  • build-essential : C/C++ 컴파일에 필요한 기본 컴파일 도구 모음이다.
  • libssl-dev : SSL/TLS 통신을 위한 OpenSSL 라이브러리 개발 헤더이다.
  • zlib1g-dev : 압축 알고리즘용 zlib 라이브러리 개발 파일이다.
  • libbz2-dev : bzip2 압축 알고리즘용 개발 라이브러리이다.
  • libreadline-dev : 터미널에서 편리한 입력을 가능하게 하는 readline 개발 라이브러리이다.
  • libsqlite3-dev : SQLite 데이터베이스 개발에 필요한 라이브러리이다.
  • wget : 파일을 HTTP, HTTPS, FTP로 다운로드할 수 있는 명령줄 도구이다.
  • curl : 다양한 프로토콜로 데이터를 송수신할 수 있는 명령줄 도구이다.
  • llvm : C/C++ 등의 언어를 위한 컴파일러 인프라 구조이다.
  • libncurses5-dev : 터미널 기반 UI(텍스트 기반 사용자 인터페이스)를 만들기 위한 ncurses 라이브러리의 개발 파일이다.
  • xz-utils : .xz 형식의 압축을 처리할 수 있는 도구이다.
  • tk-dev : GUI 애플리케이션을 만들 때 사용하는 Tk GUI 툴킷 개발 파일이다.
  • libxml2-dev : XML 파싱 및 처리 기능을 제공하는 libxml2의 개발 헤더 및 라이브러리이다.
  • libxmlsec1-dev : XML 디지털 서명 및 암호화를 위한 libxmlsec1의 개발 라이브러리이다.
  • libffi-dev : 외부 함수 호출을 위한 외부 함수 인터페이스 개발 라이브러리이다.
  • liblzma-dev : LZMA 압축 알고리즘을 위한 개발 라이브러리이다.
  • python3-openssl : 파이썬에서 OpenSSL을 사용할 수 있도록 하는 패키지이다.
  • git : 분산 버전 관리 시스템으로, 소스코드 형상 관리를 도와준다.
sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev python3-openssl git

pyenv 설치

  • 다음 명령어로 실행한다.
$ curl https://pyenv.run | bash
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   270  100   270    0     0    404      0 --:--:-- --:--:-- --:--:--   404
Cloning into '/home/evanjjh/.pyenv'...
remote: Enumerating objects: 1365, done.
remote: Counting objects: 100% (1365/1365), done.
remote: Compressing objects: 100% (725/725), done.
remote: Total 1365 (delta 826), reused 806 (delta 507), pack-reused 0 (from 0)
Receiving objects: 100% (1365/1365), 1.14 MiB | 7.48 MiB/s, done.
Resolving deltas: 100% (826/826), done.
Cloning into '/home/evanjjh/.pyenv/plugins/pyenv-doctor'...
remote: Enumerating objects: 11, done.
remote: Counting objects: 100% (11/11), done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 11 (delta 1), reused 5 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (11/11), 38.72 KiB | 1.68 MiB/s, done.
Resolving deltas: 100% (1/1), done.
Cloning into '/home/evanjjh/.pyenv/plugins/pyenv-update'...
remote: Enumerating objects: 10, done.
remote: Counting objects: 100% (10/10), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 10 (delta 1), reused 5 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (10/10), done.
Resolving deltas: 100% (1/1), done.
Cloning into '/home/evanjjh/.pyenv/plugins/pyenv-virtualenv'...
remote: Enumerating objects: 64, done.
remote: Counting objects: 100% (64/64), done.
remote: Compressing objects: 100% (57/57), done.
remote: Total 64 (delta 10), reused 23 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (64/64), 43.08 KiB | 2.15 MiB/s, done.
Resolving deltas: 100% (10/10), done.

WARNING: seems you still have not added 'pyenv' to the load path.

# Load pyenv automatically by appending
# the following to 
# ~/.bash_profile if it exists, otherwise ~/.profile (for login shells)
# and ~/.bashrc (for interactive shells) :

export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init - bash)"

# Restart your shell for the changes to take effect.

# Load pyenv-virtualenv automatically by adding
# the following to ~/.bashrc:

eval "$(pyenv virtualenv-init -)"

.bashrc 파일 설정

  • 먼저 vim을 설치한다.
sudo apt-get update
sudo apt-get install -y vim
  • .bashrc 파일을 연다
vi ~/.bashrc
  • 파일을 열면 다양한 환경변수 설정 코드가 들어 있다.

image.png

  • 맨 아래에 위 그림과 같이 복사 붙이기를 한다. (Ctrl + Insert)
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init - bash)"
  • 시스템에 반영하려면 다음과 같이 업데이트 한다.
$ source ~/.bashrc
$ eval "$(pyenv virtualenv-init -)"

pyenv 설치 확인

  • SHELL을 재시작한다.
exec $SHELL
  • pyenv 명령어 입력해서 버전 및 명령어 관련 메시지가 나오는지 확인한다.
$ pyenv
pyenv 2.5.4
Usage: pyenv <command> [<args>]

Some useful pyenv commands are:
   activate    Activate virtual environment
   commands    List all available pyenv commands
   deactivate   Deactivate virtual environment
   doctor      Verify pyenv installation and development tools to build pythons.
   exec        Run an executable with the selected Python version
   global      Set or show the global Python version(s)
   help        Display help for a command
   hooks       List hook scripts for a given pyenv command
   init        Configure the shell environment for pyenv
   install     Install a Python version using python-build
   latest      Print the latest installed or known version with the given prefix
   local       Set or show the local application-specific Python version(s)
   prefix      Display prefixes for Python versions
   rehash      Rehash pyenv shims (run this after installing executables)
   root        Display the root directory where versions and shims are kept
   shell       Set or show the shell-specific Python version
   shims       List existing pyenv shims
   uninstall   Uninstall Python versions
   update      Update pyenv, its plugins including the list of available versions
   --version   Display the version of pyenv
   version     Show the current Python version(s) and its origin
   version-file   Detect the file that sets the current pyenv version
   version-name   Show the current Python version
   version-origin   Explain how the current Python version is set
   versions    List all Python versions available to pyenv
   virtualenv   Create a Python virtualenv using the pyenv-virtualenv plugin
   virtualenv-delete   Uninstall a specific Python virtualenv
   virtualenv-init   Configure the shell environment for pyenv-virtualenv
   virtualenv-prefix   Display real_prefix for a Python virtualenv version
   virtualenvs   List all Python virtualenvs found in `$PYENV_ROOT/versions/*'.
   whence      List all Python versions that contain the given executable
   which       Display the full path to an executable

See `pyenv help <command>' for information on a specific command.
For full documentation, see: https://github.com/pyenv/pyenv#readme

pyenv 활용한 파이싼 가상 환경 구축

  • 다음 코드 실행
$ pyenv install --list
  • 파이썬 3.11.6 버전 설치
$ pyenv install 3.11.6 
Downloading Python-3.11.6.tar.xz...
-> https://www.python.org/ftp/python/3.11.6/Python-3.11.6.tar.xz
Installing Python-3.11.6...
Installed Python-3.11.6 to /home/evanjjh/.pyenv/versions/3.11.6
  • pyenv 버전 확인
$ pyenv versions
* system (set by /home/evanjjh/.pyenv/version)
  3.11.6
  • 가상환경 구축, 이름은 변경 가능
$ pyenv virtualenv 3.11.6 py3_11_6
  • 가상환경 목록 확인
$ pyenv activate py3_11_6
(py3_11_6) $ 
  • 프로젝트 경로에서 requirements.txt 파일 생성
django
gunicorn
psycopg2-binary
  • 파일 작성 후, 라이브러리 설치
(py3_11_6) $ pip install -r requirements.txt
  • main.py 생성 후 실제 라이브러리 버전 적용
import django
import gunicorn 
import psycopg2 

def check_library_versions():
    print(f"Django version: {django.get_version()}")
    print(f"Gunicorn version: {gunicorn.__version__}")
    print(f"Psycopg2 version: {psycopg2.__version__}")

def main():
    check_library_versions()

if __name__ == "__main__":
    main()
  • 작성된 코드를 실행한다.
(py3_11_6) $ python main.py 
Django version: 5.1.7
Gunicorn version: 23.0.0
Psycopg2 version: 2.9.10 (dt dec pq3 ext lo64)
  • 가상환경 종료하는 방법은 다음과 같다.
(py3_11_6) $ pyenv deactivate
$ 

pip 설치

$ pyenv global 3.11.6
$ python -m ensurepip

virtualenv 활용한 가상환경 설치

$ pip install virtualenv
$ virtualenv venv
$ source venv/bin/activate
(venv) $ pip install -r requirements.txt

파일 구조 확인

  • Linux 서버를 통해서 작업을 하는 개발자의 경우 전체적인 폴더의 흐름, 파일 확인이 어렵다.
  • 다음 패키지를 설치한다.
$ sudo apt install tree
  • 파일 구조 확인
$ tree .
.
├── hello.txt
├── main.py
├── README.md
└── requirements.txt

1 directory, 4 files

(중요) 네트워크 설정

  • VirtualBox를 열고 가상환경에서 포트포워딩 하는 과정을 진행한다.

호스트 전용(Host-Only) 네트워크

  • 가상 머신 ↔ 호스트 간에 직접 통신 가능 (추가 설정 없이 ping, ssh, scp 가능)
  • 인터넷은 불가능 (게이트웨이 없음)
  • 일반적으로 가상머신끼리 네트워크 테스트하거나, 클러스터 환경 구성 시 사용
  • 예시
    • 여러 대의 VM을 띄워서 Hadoop, Kubernetes 등의 클러스터 환경 구성 시, 노드 간 통신에 사용

NAT(Network Address Translation) 네트워크

  • 가상 머신은 인터넷 사용 가능 (예: apt update, 웹 브라우징 등)
  • 호스트가 VM에 접속하려면 포트 포워딩 설정 필요
  • VM은 마치 NAT 라우터 뒤에 있는 것처럼 동작함
  • 다수의 VM을 연결해 내부 네트워크처럼 구성할 수 있음 (NAT Network 탭 활용)
  • 예시
    • VM 안에서 Flask 웹 서버를 8000번 포트로 실행하고, 호스트 PC에서는 localhost:8000으로 접속 (포트포워딩을 통해)

현재 설정된 포트 포워딩 규칙

  • DHCP 서버 : 가상 머신에 IP를 자동 할당해줌
  • 호스트 IP : 실제 PC (비워두면 기본 IP 사용)
  • 호스트 포트 : 실제 PC에서 접근할 때 사용하는 포트
  • 게스트 IP : 가상 머신의 IP 주소
    • enp0s3inet 10.0.2.15 을 입력한다.
    • 이 부분은 각 PC 마다 다를 수 있으니, 해당 IP 번호를 입력한다.
$ ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        ether a2:6c:75:35:3b:ac  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 30 overruns 0  carrier 0  collisions 0

enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.2.15  netmask 255.255.255.0  broadcast 10.0.2.255
        inet6 fe80::a00:27ff:fecb:782d  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:cb:78:2d  txqueuelen 1000  (Ethernet)
        RX packets 20595  bytes 14788976 (14.7 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 15606  bytes 8909092 (8.9 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 20277  bytes 9917982 (9.9 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 20277  bytes 9917982 (9.9 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

image.png

  • 포트번호 : 22
    • SSH 접속 (호스트에서 localhost:22로 접속 시, VM의 22번 포트로 연결됨)
  • 포트번호 : 8000
    • 웹서버/애플리케이션용. VM에서 실행 중인 서버를 호스트에서 접근 가능
  • 포트번호 : 80
    • HTTP 웹서버용. 호스트의 localhost:80 접근 시 VM의 80포트로 연결

pyyaml 설치

  • 간단한 실습 위해 필수 라이브러리 설치
$ pyenv activate py3_11_6
(py3_11_6) $ pip install pyyaml

폴더 생성, 파일 생성

  • ex01 > yaml_practice.yml
  • 파일 생성은 다음과 같다.
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
    - name: nginx
      image: nginx:latest
    - name: ubuntu
      image: ubuntu:latest

Jupyterlab 포트포워딩

  • 포트번호가 8888 이다. 해당 포트를 추가하고, 관련 라이브러리를 실행한다.
  • 정상적으로 Local에서도 실행이 되는지 확인한다.
(venv) $ pip install jupyterlab
(venv) $ jupyterlab

django 프로젝트

  • 프로젝트 디렉터리 구조를 확인한다.
  • django 첫번째 프로젝트는 ex02에서 시작할 것이다.
$ tree -I venv
.
├── ex01
│   ├── ex01.ipynb
│   └── yaml_practice.yml
├── ex02
├── hello.txt
├── main.py
├── README.md
└── requirements.txt
  • 터미널 명령어 경로를 ex02로 이동한후 아래와 같이 명령어를 입력한다.
  • 기본적인 파일을 제공해주는 것을 확인할 수 있다.
(venv) ex02$ django-admin startproject myapp
(venv) ex02$ tree .
.
└── myapp
    ├── manage.py
    └── myapp
        ├── asgi.py
        ├── __init__.py
        ├── settings.py
        ├── urls.py
        └── wsgi.py

django 설정파일

  • 파일 경로 : myapp > myapp > settings.py
  • 다음과 같이 코드를 수정한다.
# ALLOWED_HOSTS = [] # Before
ALLOWED_HOSTS = ['*'] # Now

django migrate

  • 다음과 같이 코드를 실행하여 database에 저장한다.
(venv) myapp$ 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

서버 실행

  • runserver 명령어 이용해서 django 프로젝트 실행
  • 정상적으로 잘 나오는지 확인한다.
(venv) myapp$ python manage.py runserver 0.0.0.0:8000
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
March 26, 2025 - 05:54:53
Django version 5.1.7, using settings 'myapp.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.

[26/Mar/2025 05:54:55] "GET / HTTP/1.1" 200 12068
Not Found: /favicon.ico
[26/Mar/2025 05:54:55] "GET /favicon.ico HTTP/1.1" 404 2207

Screenshot 2025-03-26 at 2.55.21 PM.png

django 이미지 빌드

  • django 프로젝트를 컨테이너 이미지로 빌드하기
    • 디렉터리 정리
    • Dockerfile 파일 작성
    • 이미지 빌드

디렉터리 정리

  • ex02 복사해서 ex03 디렉터리 생성
  • ex03 디렉터리로 이동하여 tree 명령어 이용해 디렉터리 구조 확인
$ cp -r ex02 ex03
$ ls
ex01  ex02  ex03  hello.txt  main.py  README.md  requirements.txt  venv
$ cd ex03
ex03$ tree ./ -L 3
./
└── myapp
    ├── db.sqlite3
    ├── manage.py
    └── myapp
        ├── asgi.py
        ├── __init__.py
        ├── __pycache__
        ├── settings.py
        ├── urls.py
        └── wsgi.py

requirements.txt 파일 작성

  • 파일 내부에 django 버전 적어주기
  • 이미지 생성 시 필요한 라이브러리 정리하기
django==4.2.7

Dockerfile 파일 작성

  • Dockerfile 파일 작성
# 파이썬 3.11.6 버전의 베이스 이미지를 사용
FROM python:3.11.6 

# 작업 디렉토리를 /usr/src/app으로 설정
WORKDIR /usr/src/app 

# 현재 디렉토리의 모든 파일을 컨테이너의 작업 디렉토리로 복사
COPY . .

# pip를 최신 버전으로 업그레이드
RUN python -m pip install --upgrade pip 

# requirements.txt에 명시된 패키지들을 설치
RUN pip install -r requirements.txt 

# myapp 디렉토리로 작업 디렉토리 변경
WORKDIR ./myapp

# Django 개발 서버를 0.0.0.0:8000 포트로 실행
CMD python manage.py runserver 0.0.0.0:8000

# 8000번 포트를 외부에 노출
EXPOSE 8000 

Docker 사용자 그룹 지정

  • 현재 사용자를 docker 그룹에 추가
sudo usermod -aG docker $USER
  • 그룹 변경사항을 적용하기 위해 시스템에서 로그아웃했다가 다시 로그인하거나, 다음 명령어를 실행
newgrp docker

Docker 이미지 빌드하기

  • 도커 이미지를 바탕으로 컨테이너 형태로 배포함
ex03$ docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED              SIZE
myweb01      latest    1eecd009bf59   About a minute ago   1.07GB

Docker 컨테이너 실행

  • 컨테이너 실행 및 접속 확인
ex03$ docker container run -d -p 8000:8000 myweb01
6c35e144604cde5f03526f7a32d44f3328fafc4f01da5af715b0932c573729e0

ex03$ docker container ls
CONTAINER ID   IMAGE     COMMAND                  CREATED              STATUS              PORTS                                         NAMES
6c35e144604c   myweb01   "python manage.py ru…"   About a minute ago   Up About a minute   0.0.0.0:8000->8000/tcp, [::]:8000->8000/tcp   quizzical_poitras

Screenshot 2025-03-27 at 12.59.42 PM.png

docker inspect 명령어 확인

$ docker network inspect bridge | grep IPv4Address
                "IPv4Address": "172.17.0.2/16",

Nginx, django 연동 후 실행

  • Nginx 컨테이너 실행 후, gunicorn을 통해 Nginx와 django 연동
  • ex04 폴더 생성
$ mkdir ex04
$ ls
ex01  ex02  ex03  ex04  hello.txt  main.py  README.md  requirements.txt  venv
$ cd ex04
ex04$ docker image build . -t mynginx01
  • 마지막 단계로 앞서 빌드한 이미지 활용해 컨테이너 실행
ex04$ docker container run -p 80:80 -d mynginx01
37d48bec5788f13b611e13a607b0d2694abec6502dbe6547ebbe1c88def48697
  • 현재 실행중인 docker container 목록
ex04$ docker container ls
CONTAINER ID   IMAGE       COMMAND                  CREATED          STATUS          PORTS                                         NAMES
37d48bec5788   mynginx01   "/docker-entrypoint.…"   2 minutes ago    Up 2 minutes    0.0.0.0:80->80/tcp, [::]:80->80/tcp           dreamy_chandrasekhar
6c35e144604c   myweb01     "python manage.py ru…"   40 minutes ago   Up 40 minutes   0.0.0.0:8000->8000/tcp, [::]:8000->8000/tcp   quizzical_poitras

Screenshot 2025-03-27 at 1.45.05 PM.png

gunicorn을 통한 연동 개요, 디렉터리 정리

  • django와 nginx 연동
    • 두개의 웹서버를 연동하기 위해서는 gunicorn이 필요함
  • 디렉터리 정리를 진행한다. 우선 ex05 폴더 생성을 한다.
$ ls
ex01  ex02  ex03  ex04  ex05  hello.txt  main.py  README.md  requirements.txt  venv
  • 아래와 같이 명령어를 입력한다.
    • ex03이 소스(원본)
    • ex04와 ex05가 목적지
$ cp -r ex03 ex04 ex05 
$ ls
$ cd ex05
ex05$ ls
ex03 ex04
  • 위 코드에서 mv 명령어 활용해서 폴더 이름 재정의
  • 디렉터리 최종 확인
ex05$ mv ex03 myDjango02
ex05$ mv ex04 myNginx02
ex05$ ls
myDjango02  myNginx02

ex05$ tree ./ -L 2
./
├── myDjango02
│   ├── Dockerfile
│   ├── myapp
│   └── requirements.txt
└── myNginx02
    └── Dockerfile

django 파일 수정

  • djnago requirements.txt 파일 수정
django==4.2.7
gunicorn==20.1.0
  • django Dockerfile 파일 수정
# 파이썬 3.11.6 버전의 베이스 이미지를 사용
FROM python:3.11.6 

# 작업 디렉토리를 /usr/src/app으로 설정
WORKDIR /usr/src/app 

# 현재 디렉토리의 모든 파일을 컨테이너의 작업 디렉토리로 복사
COPY . .

# pip를 최신 버전으로 업그레이드
RUN python -m pip install --upgrade pip 

# requirements.txt에 명시된 패키지들을 설치
RUN pip install -r requirements.txt 

# myapp 디렉토리로 작업 디렉토리 변경
WORKDIR ./myapp

# Django 개발 서버를 0.0.0.0:8000 포트로 실행
# gunicorn 사용
CMD ["gunicorn", "myapp.wsgi:application", "--bind", "0.0.0.0:8000"]

# 8000번 포트를 외부에 노출
EXPOSE 8000 
  • 경로 이동 후, 새로운 도커 이미지 파일 빌드
docker image build . -t myweb02

Nginx 파일 수정

  • default.conf 파일 수정
  • djangotest는 django를 이용해 생성하게 될 컨테이너 이름
  • Nginx는 80번 포트로 받은 요청을 djangotest 컨테이너의 8000번 포트로 전송한다는 의미
# Django 서버를 위한 업스트림 설정
upstream myweb{
    # Django 서버의 주소와 포트
    server djangotest:8000;
}

# Nginx 서버 설정
server{
    # 80번 포트에서 리스닝
    listen 80;
    # 서버 이름 설정
    server_name localhost;

    # 루트 경로(/) 요청에 대한 처리
    location /{
        # myweb 업스트림으로 프록시
        proxy_pass http://myweb;
    }
    
}
  • Dockerfile 수정
# 베이스 이미지
FROM nginx:1.25.3 

RUN rm /etc/nginx/conf.d/default.conf

COPY default.conf /etc/nginx/conf.d/

# 컨테이너 실행 시 Nginx 시작
CMD ["nginx", "-g", "daemon off;"]

# 포트 오픈
EXPOSE 80
  • 도커 이미지 빌드
$ docker image build . -t mynginx02
  • 도커 이미지 목록 확인
$ docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED             SIZE
mynginx02    latest    bdf136c7bb2e   28 minutes ago      192MB
myweb02      latest    1fd3a0559ba2   About an hour ago   1.07GB

django와 Nginx 연동 후 컨테이너 실행

  • 컨테이너 실행
$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
f13e348089ab   bridge    bridge    local
4ffcf82ed348   host      host      local
2f36153c3c11   none      null      local
  • 도커 컨테이너 네트워크
$ docker network create mynetwork02
c4836e811ccf7bb87215c88dd478fb5c28a71bee06699dc26875442a076a7285
  • djgnaotest 컨테이너 실행
$ docker container run -d --name djangotest --network mynetwork02 myweb02
  • nginxtest 컨테이너 실행
$ docker container run -d --name nginxtest --network mynetwork02 -p 80:80 mynginx02
  • 컨테이너 목록 확인
$ docker container ls --all
CONTAINER ID   IMAGE       COMMAND                  CREATED              STATUS              PORTS                                 NAMES
c8bfefdd91da   mynginx02   "/docker-entrypoint.…"   5 seconds ago        Up 4 seconds        0.0.0.0:80->80/tcp, [::]:80->80/tcp   nginxtest
68107133fcfe   myweb02     "/bin/bash -c 'gunic…"   About a minute ago   Up About a minute                                         djangotest

테스트

  • 127.0.0.1:80 실행했을 때, django 화면이 나오면 성공

    Screenshot 2025-03-27 at 4.36.48 PM.png

  • 이번엔 코드로 두 컨테이너가 서로 통신하는지 확인

$ docker network inspect mynetwork02
[
    {
        "Name": "mynetwork02",
        "Id": "c4836e811ccf7bb87215c88dd478fb5c28a71bee06699dc26875442a076a7285",
        "Created": "2025-03-27T15:57:04.456240768+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv4": true,
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "68107133fcfee3e5c2f511d3eb6ff3b48827c3eaee59760b1207456da07cac51": {
                "Name": "djangotest",
                "EndpointID": "8231723f28bd77111341d62539b861f8bc713bb437a87930a89fc54329737f1a",
                "MacAddress": "7e:e4:e5:e8:e5:75",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            },
            "c8bfefdd91daed6ca9d4586b368a6a0cf9107fa073ee24ae0b115f63c6779abf": {
                "Name": "nginxtest",
                "EndpointID": "8567d049503d2901a8ab33161085cdbd58718ca3e0044d8af4b4c27d79607d44",
                "MacAddress": "56:20:40:f1:44:34",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]