안녕하세요. 바른호랑이입니다.
이번 게시글에서는 생성한 컨테이너를 외부 네트워크에 오픈하는 방법에 대해서 알아볼 예정입니다.
게시글은 '시작하세요! 도커/쿠버네티스 친절한 설명으로 쉽게 이해하는 컨테이너 관리'를 기반으로 작성하였으니 참고 바랍니다.
Docker는 기본적으로 컨테이너에 172.17.0.x와 같은 가상의 IP를 순차적으로 할당하며, 이는 컨테이너 내부에서 ifconfig 명령어를 사용하면 확인할 수 있습니다. 만약 컨테이너 접속 시 ifconfig 명령어가 작동하지 않는다면 아래의 코드를 실행한 후 진행하면 됩니다.
# apt update
apt update
# install net-tools
apt install net-tools
# check network interface
ifconfig
ifconfig 명령어로 확인한 네트워크 정보를 살펴보면 Docker의 NAT(Network Address Translation, 사설 네트워크에 속한 여러 개의 호스트가 하나의 공인 IP주소를 사용하여 인터넷에 접속하기 위해 사용하는 서비스로 IP패킷에서 TCP/UDP 포트 숫자와 소스 및 목적지의 IP 주소 등을 재기록하며 라우터를 통해 네트워크 트래픽을 주고받는 기술을 지칭함.) IP인 172.17.0.2를 할당받은 eth0 인터페이스와 로컬 호스트인 lo 인터페이스가 있는 것을 확인할 수 있습니다. 추가적인 설정을 하지 않았다면 외부에서 해당 컨테이너로는 접속이 불가능하며 Docker가 설치된 호스트에서만 접근이 가능하기에 만약 외부에 해당 컨테이너의 애플리케이션을 노출하기 위해서는 eth0의 IP와 포트를 호스트의 IP와 포트에 바인딩해줘야 합니다.
이를 실제로 알아보기 위해서 아래의 명령어를 통해 80번 포트로 컨테이너의 포트와 호스트 포트가 바인딩되어 연결할 수 있게 설정한 컨테이너를 생성한 후 아래의 명령어로 apache web server를 설치합니다.
# crate test container
# -p옵션 사용 방법: -p [host port]:[container port]
sudo docker run -i -t --name mywebserver -p 80:80 --detach-keys='ctrl-x' ubuntu:24.04
# install necessary packages
apt update
apt install apache2 -y
service apache2 start
# 호스트의 특정 IP를 사용하여 포트를 오픈하려면 192.168.0.100:7777:80과 같이 바인딩할 IP와 포트를 명시
# 여러개의 포트를 외부에 개발하려면 -p 옵션을 여러 번 써서 설정
# 오픈한 포트정보를 확인하기위해서는 sudo docker ps -a 명령어를 통해 확인 가능
# 예시) sudo docker run -i -t -p 3306:3306 -p 192.168.0.100:7777:80 ubuntu:24.04
설치가 완료되면 [Docker 엔진 호스트의 IP]:80으로 접근하여 정상적으로 접속이 되는지 확인합니다.
실제로 apache 서버가 설치된 것은 컨테이너의 내부로 호스트에는 어떠한 영향도 주지 않으며, 호스트의 IP와 포트를 컨테이너의 IP와 포트로 연결한다는 개념을 이해하는 것이 매우 중요합니다. Apache web server에 접근하는 구조는 아래 그림과 같습니다.
대부분의 서비스는 여러 에이전트와 DB 등이 연결되어 동작하는 것이 일반적이며, 이를 컨테이너화할 경우 여러 개의 애플리케이션을 하나의 컨테이너에 전부 설치(All-in-one 컨테이너)할 수도 있고, 하나의 컨테이너에 하나의 애플리케이션만 설치하는 식으로 분할(분리된 애플리케이션 컨테이너)할 수도 있습니다. 후자의 경우 컨테이너 간의 독립성을 보장함과 동시에 애플리케이션의 버전 관리, 소스코드 모듈화등이 보다 쉬워지므로 Docker 커뮤니티 및 Docker 홈페이지에서도 권장하는 구조이며, 이는 하나의 컨테이너에 하나의 프로세스만 실행하는 것을 추구하는 Docker의 철학과도 일치합니다.
이와 같이 하나의 컨테이너의 하나의 프로세스만 실행하는 간단한 실습을 위해 아래의 코드로 DB 컨테이너와 워드프레스 웹 서버 컨테이너를 각각 생성해 봤습니다.
# create db server container
sudo docker run -d \
--name wordpressdb \
-e MYSQL_ROOT_PASSWORD=password \
-e MYSQL_DATABASE=wordpress \
mysql:5.7
# create wordpress web serve container
sudo docker run -d \
-e WORDPRESS_DB_HOST=mysql \
-e WORDPRESS_DB_USER=root \
-e WORDPRESS_DB_PASSWORD=password \
--name wordpress \
--link wordpressdb:mysql \
-p 80 \
wordpress
생성이 정상적으로 된 후에 ps 명령어를 통해 생성된 컨테이너 현황을 확인해 봤을 때 이상이 없는 것을 검증하였습니다. 워드프레스 웹 서버 컨테이너의 포트 옵션을 지정할 때 호스트 포트를 별도로 지정하지 않았기에 포트를 확인해 봤는데, 호스트의 32768번 포트와 컨테이너의 80번 포트가 바인딩되어 연결되어 있는 것을 알 수 있었습니다. 바인딩된 포트를 확인한 후에는 정상접속이 되는지를 확인하기 위해 [Docker 엔진 호스트의 IP 주소]:32768로 접속 테스트를 진행하였고, 아래와 같이 이상 없이 접속이 되는 것을 확인할 수 있었습니다.
추가적으로 이번에는 컨테이너를 생성하고 실행할 때 run명령어를 쓴 것은 기존과 동일했지만 -i, -t 옵션이 아닌 다른 옵션들을 사용하였으며, 각 옵션에 대한 설명은 아래와 같습니다.
ㆍ-d 옵션: -i, -t 옵션이 컨테이너 내부로 진입하도록 attach 가능한 상태(표준 입출력이 활성화된 상호작용이 가능한 셸 환경을 사용할 수 있는 상태)로 설정한다면, -d는 Detached 모드로 컨테이너를 실행합니다. Detached 모드는 컨테이너를 백그라운드에서 동작하는 애플리케이션으로써 실행하도록 설정합니다. 해당 모드는 컨테이너 내부에서 프로그램이 터미널을 차지하는 foreground로 실행되어 사용자의 입력을 받지 않으며, 반드시 컨테이너에서 프로그램이 실행되어야 합니다.(foreground 프로그램이 실행되지 않으면 컨테이너가 종료되고, 컨테이너를 실행시킬 수 없음)
# foreground로 실행하는 프로그램 없이 -d 옵션을 사용하여 컨테이너를 생성, 실행
sudo docker run -d --name detached_test ubuntu:24.04
# check status
sudo docker ps -a
foreground로써 동작하는 프로그램이 있게 하면서 -i, -t옵션을 사용하면 이미 실행 중인 프로그램이 있기 때문에 상호 입출력이 불가능하고 단순히 foreground로 설정된 프로그램이 동작하는 것만 볼 수 있습니다. 이는 컨테이너가 각기 하나의 모니터를 기본적으로 가지고 있기 때문이며, 이에 대해서 보다 명확하게 이해하고 싶다면 여러 개의 터미널을 열어 하나의 컨테이너에 접속해보면 보다 직관적으로 이해할 수 있습니다.
# foreground로 실행하는 프로그램이 있는 상태에서 -i -t 옵션으로 컨테이너 생성
sudo docker run -i -t \
--name mysql_attach_test \
-e MYSQL_ROOT_PASSWORD=password \
-e MYSQL_DATABASE=wordpress \
mysql:5.7
ㆍ-e 옵션: 컨테이너 내부의 환경변수를 설정하는 옵션으로 컨테이너화된 애플리케이션은 환경변수에서 값을 가져와 쓰는 경우가 많으므로 자주 사용하는 옵션 중 하나입니다. 설정한 환경변수는 아래의 코드를 통해 확인할 수 있습니다.
# check environment variable
# exec container bash
sudo docker exec -i -t wordpressdb /bin/bash
# echo ${ENVIRONMENT_NAME}
echo $MYSQL_ROOT_PASSWORD
exec 명령어를 사용하면 컨테이너 내부에서 명령어를 실행한 결괏값을 반환받을 수 있으며, -i, -t 옵션을 사용하여 /bin/bash를 상호입출력이 가능한 상태로 사용하는 것도 가능합니다. 창에서 빠져나오는 방법도 기존 컨테이너를 빠져 나오는 것도 기본적으로 동일하지만 -d옵션으로 실행 중인 foreground 프로그램이 있는 경우에는 ctrl+d를 사용하여 빠져나오더라도 컨테이너가 종료되지 않는다는 것에서 약간 차이가 있습니다.
ㆍ--link 옵션: 특정 컨테이너에서 다른 컨테이너로 접근하는 방법 중 가장 간단한 것은 NAT로 할당받은 IP를 직접 사용하는 것이지만 Docker 엔진의 경우 내부 IP를 컨테이너를 시작시킬 때마다 172.17.0.2, 3, 4... 와 같이 순차적으로 할당하므로 이를 직접 사용하기는 어려움이 있습니다. 이때 --link 옵션을 사용할 수 있는데, 이는 해당 옵션이 alias를 활용하여 접근하도록 설정하기 때문입니다. 즉, '--link [container name]:[alias]'라는 옵션을 주면 특정 컨테이너를 alias로 설정할 수 있고, 이를 환경변수에 선언함으로써 직접적인 NAT IP를 모르더라도 접속이 가능해집니다. 다만 --link에 입력된 컨테이너가 실행 중이지 않거나 존재하지 않는다면 --link를 적용한 컨테이너 또한 실행할 수 없다는 것을 유의해야 합니다.
'IT & 데이터 사이언스 > Data Engineering' 카테고리의 다른 글
[Docker] Docker 네트워크 (1) | 2024.08.08 |
---|---|
[Docker] Docker 볼륨 (5) | 2024.08.05 |
[Docker] Docker 엔진의 기본 단위와 컨테이너 생성, 삭제 (0) | 2024.07.25 |
[Docker] Docker란? (0) | 2024.07.18 |
[Airflow] Apache Airflow 살펴보기 (2) | 2024.07.15 |
댓글