[:en][Docker-Compose] Django + PostgreSQL[:]

[:en][Docker-Compose] Django + PostgreSQL[:]

[:en]

When you need to launch multiple containers that work as a single application, it is difficult to manage with single Dockerfile.

That’s why we need to use “docker compose” so that we can manage our containers from a higher level.

The application that we will test is a simple Django application.

The database is PostgreSQL, and it will also be installed using Docker.



Normally, it is not recommended to install the database using Docker. The database should be running on their own, and other application should be able to access at any time, moreover, the data should be persistent as well. If you put the database into the docker composer, then every time when you need to deploy the new application, you have to redeploy your database. (Of course, there is a way to keep the data. However, since it is recommended to use the database service from the cloud infrastructures such as Azure or AWS, so not worthy of arguing!)

Anyway, I just wanted to show how to handle multi-container installation when one container is dependent on the other container.

The challenging part in this scenario is when you build the Django application it needs to be connected with the database before it actually runs.

Then you may think, “What’s the problem?”.

Well, the problem is, if Django finished its launching earlier than PostgreSQL, it will raise the error showing it cannot find the database and Docker will stop.

Then you may think, “Maybe we can put some waiting time?”.

Well, you cannot just put an arbitrary waiting time because from some system it might be installed faster than the others or vice versa.

Here I introduce the common way to deal with dependent multi-container installation using docker compose.

Introducing the sample application

Screen Shopt
Welcome to my humble Django application

This is a just website keeps adding a new image as a card-UI every time user refresh this page.

It will be much easier if you see the following code.

As you can see, every time the user calls the index page, it will call the random_picture function and store the image as a base64 encoded version into the database. Then return all the posts data to render into the HTML page.

Pretty simple, right?

Writing docker-compose.yml

I assume that you can intuitively understand the code.

There are two services (containers): ‘app’ and ‘postgres’.

The ‘app’ container will be built using Docker file in the root path.

The ‘postgres’ container will be built using Docker file in ‘postgres’ folder.

The most important parameter is “links”. Since we are opening this database to the ‘app’ container, there should be a link between ‘app’ and ‘postgres’ containers. (If you open the database port publicly, then you don’t have to use this parameter.)

Now, let’s take a look Dockerfile for ‘app’ container.

I think nothing is special until line 6.

And if you have ever used docker before, you would end up with CMD [“python,” “run,” something something].

However, since we are building our application from the very scratch of Django, we need a further process.

Therefore, we put all the extra commands into ‘entry_point.sh’ file.

The most important part of this shell script is from line 4 to 7.

This loop will repeat until “python manage.py migrate” works properly (not raising an error.)

Of course, there must be several ways to check the status of database such as sending “health check” stuff.

You can use whatever approaches that you want, just remember to repeat that process “until it works”.

Alright that’s it!

You can find the complete source from here!



[:ko]

여러 개의 컨테이너로 이루어진 어플리케이션을 도커를 이용해서 배포하려 하면, 한 Dockerfile로 해결이 안 되는 경우가 많습니다.

그래서 컨테이너들을 한 번에 관리하기 위해 docker compose를 사용합니다.

이번에 테스트할 어플리케이션은 Django로 작성된 간단한 웹사이트입니다.

데이터베이스는 PostgreSQL이며 마찬가지로 Docker 이용해서 설치됩니다.



그런데 일반적으로 DB는 도커를 이용해서 설치하는 게 권장되지 않습니다. DB는 일반적으로 독립적으로 계속 운용이 되면서, 어떤 앱에서든 자유롭게 접속할 수 있고 항상 정상적으로 응답을 하고 데이터도 계속 저장을 한 상태로 있어야 합니다. 만약에 도커를 이용해서 배포를 하면, 앱이 업데이트될 때마다 데이터 베이스도 업데이트가 되어 버립니다. 물론 데이터를 따로 저장소에 저장하며 도커를 운용하는 방법이 있긴 한데. 요즘 클라우드 서비스를 이용하면 보통 DB용 서비스를 따로 제공해주기 때문에, DB 따로 설치하는 경우는 좀 드뭅니다.

아무튼, 이번에 보여드리고 싶던 예제는, 한 컨테이너가 다른 컨테이너에 종속되어 있을 때 어떻게 멀티 컨테이너 배포를 하는지에 대한 방법입니다.

이번 예제에서 고민해야 될 부분은 Django 같은 경우에는 디비가 연결이 된 상태에서 이제 시작이 되어야 한다는 것입니다.

그러면 뭐가 문제지라고 생각할 수 있는데,

만약에 컨테이너들이 각자 이제 이미지를 다운받고 설치를 시작하고 런칭을 한다고 치면, 장고의 컨테이너가 PostgreSQL보다 먼저 시작을 하려고 할때, 데이터베이스를 찾을 수 없다는 에러를 뱉으면서 도커가 중지되는 경우가 발생할 수 있습니다.

그러면 약간 기다리는 Sleep 같은 걸 주면 되지 않을까?라고 생각할 수 있지만,

맞는 말이긴 하지만, 앱이 배포되는 환경이 다 다르기 때문에 딱 어떤 시간을 정해서 줄 수는 없습니다.

자 그럼, 지금부터 docker compose를 이용한 multi container 배포에 대해 알아보겠습니다!

샘플 어플리케이션 소개

Screen Shopt
Welcome to my humble Django application

위의 사진이 예제 어플리케이션인데, 그냥 새로고침 할 때마다 임의의 이미지를 화면아 카드 UI 형태로 뿌려주는 간단한 웹사이트입니다.

코드를 보면 쉽게 이해가 될 겁니다.

위에서 보이는 바와 같이, 유저가 index page에 접속할 때마다, random_picture함수가 불러지고, 그 함수 안에서는 image를 다운로드하고, base64로 인코딩 된 상태로 데이터베이스에 저장하는 방식입니다. 그리고 전체 포스팅을 불러와서 html에 뿌려주는 것으로 앱이 마무리가 됩니다.

간단하죠?

docker-compose.yml 작성하기

어느 정도 위의 코드를 이해하실 수 있다고 가정하고 진행하겠습니다.

위에 보면 두 개의 서비스 (컨테이너)가 있습니다.: ‘app’과 ‘postgres’.

‘app’ 컨테이너는 루트 디렉토리에 있는 Docker file을 이용해서 설치가 될 것이고, ‘postgres’ 컨테이너는 ‘postgres’ 폴더에 있는 Dockerfile을 이용해서 설치가 될 것입니다.

여기서 가장 중요한 파라미터는 ‘links’인데, app 컨테이너가 postgres컨테이너의 포트를 자유롭게 접속하려면, 이렇게 이 두 앱은 서로 연결이 되었다는 것을 명명해줘야 합니다. (물론, 그냥 포트를 콘테이너 밖으로 다 오픈해버리면 상관없긴 합니다만..)

이제 app 컨테이너가 사용하는 Dockerfile을 보도록 하겠습니다.

6번째 줄까지는 크게 특별한 내용이 없습니다.

도커를 써보셨던 분들이라면, 마지막에 python run 어쩌고 저쩌고 뭐 이렇게 끝나셨을 겁니다.

그런데 저희는 장고 앱을 완전 스크래치부터 빌드하다 보니까, 추가적인 작업을 좀 더 해줘야 합니다.

그래서 ‘entry_point.sh’ 파일에 필요한 명령어들을 모두 넣겠습니다.

여기서 가장 중요한 부분은 4번에서 7번 줄입니다.

이 루프 문은 python manage.py migrate가 정상적으로 완료될 때까지 계속 반복됩니다.

물론 PostgreSQL에 “health check”같은 요청을 보내서 확인하는 방법도 있습니다.

어떤 방법을 쓰든 가장 중요한 건 정상적으로 작동될 때까지, 중요한 길목에 있는 명령을 반복적으로 실행해주는 것입니다.

끝!

여기서 완성된 코드를 볼 수 있습니다.



[:]

댓글 남기기

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.

%d 블로거가 이것을 좋아합니다: