docker expose 명령어를 알아봅시다.

도커 2022. 12. 19. 05:15

 안녕하세요. 이번 시간에는 docker에서 expose 명령어에 대해서 알아보겠습니다.

 


  현재 제 fastapi 프로젝트 구조입니다. docker-compose가 추가되었고, models.py와 db.py가 추가되었습니다. psycopg2-binary와 sqlalchemy가 새로 설치되었습니다. 실습하기 위한 프로젝트 세팅을 해 봅시다.

 

 

 먼저 ddl/schema.sql입니다. public.test가 없는 경우에만 생성하는 DDL 문입니다. title을 pk로 걸어놓았습니다.

 

 

 db.py입니다. 데이터베이스와 관련된 정보들을 관리합니다. 저 정보들에 대한 것은 fastapi를 공부할 때 다시 언급해 보도록 하겠습니다. 여기에서 중요한 것은 DATABASE_URL이라는 환경 변수를 가져와서, 엔진을 생성하는 데 쓴다는 것입니다.

 

 

 models.py입니다. table 이름이 "test"인 모델은 title인 컬럼만 있습니다. pk가 true이고, string 형태입니다.

 

 

 main.py입니다. read_root가 조금 바뀌었는데요. test 테이블로부터 모든 정보를 읽어온 다음에, "Hello fast api"를 리턴합니다. 데이터 베이스 연결이 안 되거나, 테이블이 없거나 하면 서버 에러가 떨어질 겁니다.

 


 이제, docker-compose 파일을 보겠습니다.

 

 postgres의 environment는 POSTGRES_PASSWORD만 설정해 놓았습니다. fastapi의 environment는 DATABASE_URL만 있어요. 다음에 fastapi는 docker-compose.yml이 있는 경로에 있는 Dockerfile을 읽어서 build 합니다. ports는 8000:8000으로 맵핑되어 있고요.

 

 9 ~ 10번째 줄은 postgres의 5432번 포트를 expose 한다는 것을 의미합니다. 이 명령어가 무엇을 하는 것인지 알아보면 되겠군요. 다음, 11 ~ 12번째 줄은 data 디렉토리가 비어 있는 채로 컨테이너를 시작할 때 ddl 폴더 내에 있는 스크립트들을 실행시키기 위해 적어놓았습니다. 위 예에서는 ddl/schema.sql이 실행되어서, test 테이블이 없는 경우, 생성되겠네요.

 

 

 이제 127.0.0.1:8000으로 접근해 보겠습니다. 그랬더니, Hello fast api가 잘 실행됨을 알 수 있습니다.

 


 이제, expose 부분을 주석 처리해 보겠습니다.

 

 Interal Server Error가 떨어졌습니다. 로그를 보겠습니다.

 

 

 어? 서버가 request를 수행하기 전에 비정상적으로 종료되었답니다. 여기서 fastapi가 db에 요청을 보내는 쪽이므로, 클라이언트는 fastapi가 되고 서버가 postgres가 되겠습니다. 그런데, 사실 postgres 서버는 닫힌 게 아닙니다. 단지, 5432번 port를 열어놓지 않을 뿐입니다. 이 상황을 정리해 보겠습니다.

 

 

 expose 5432로, postgres 컨테이너가 실행될 때 5432번 포트로 listen 하게 하였습니다. 이 경우 fastapi에서 postgres:5432로 접근하려고 할 때, 접근할 수 있습니다.  

 

 

 그런데, expose를 주석 처리하면, postgres가 실행될 때, 5432번 포트로 listen 하고 있지 않습니다. 고로, 통신에 실패하게 됩니다. 이로 미루어 보았을 때, expose는 포트를 열어서, 안에 있는 컨테이너들과 통신을 하기 위해 쓰는 명령어임을 알 수 있어요.

 

 


 이제 port와 차이점을 알아봅시다. expose는 바깥에 port를 노출하지 않습니다. 즉, 바깥 세상과 컨테이너 안을 연결하는 통로를 만들지 않습니다. 단지 안에 있는 컨테이너들끼리 통신을 하기 위한 포트를 엽니다.

 

 

 fastapi 서비스를 아래와 같이 바꿔 봅시다. ports 대신에 expose 8000을 사용하였습니다.

 

 다시 127.0.0.1:8000으로 접속해 보면, 로딩중이라는 메세지만 뜨다가 연결할 수 없다는 말이 뜹니다.

 

 

 내부에 있는 fastapi와, 외부를 연결하는 어떠한 길도 없기 때문입니다. 이것이 port와의 차이점이라고 할 수 있겠습니다.