📢 해당 포스트는 Docker Compose를 사용하여 여러 컨테이너들을 하나의 서비스로 묶어 관리하고 호스트 PC에 설치된 httpd(Apache)를 통해 특정 도메인과 도커 컨테이너를 연결하는 과정을 설명합니다.
🛠️ 참고
Virtualbox - Oracle VM Virtualbox
Linux OS - Rocky Linux
HTTPD - Apache
0. Docker Compose 개념
docker-compose.yml 파일을 사용해 하나의 가상 서버에서 여러 개의 컨테이너를 하나의 서비스로 정의해 컨테이너를 묶음으로 관리할 수 있다.
만약 Docker Compose를 사용하지 않는다면 컨테이너를 하나 하나씩 run 해야하는 번거러움이 있다. 하지만 Docker Compose를 사용하면 한번의 명령어로 설정 파일 안에 여러 개의 컨테이너들을 관리할 수 있다.(각 컨테이너들의 의존성, 네트워크, 볼륨 등등)
정말 편하긴 하더라.. 이제 docker run 안해도 된다!
1. Docker Compose 설치
# 도커 깃허브 저장소에서 Docker Compose 다운로드
[root@localhost ~]# curl -L https://github.com/docker/compose/releases/download/1.11.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 8052k 100 8052k 0 0 4269k 0 0:00:01 0:00:01 --:--:-- 6290k
# 권한 부여
[root@localhost ~]# chmod +x /usr/local/bin/docker-compose
# 버전 확인
[root@localhost ~]# docker-compose -v
docker-compose version 1.11.0, build 6de1806
2. docker-compose.yml 생성
💡 하위 항목은 탭(Tab)이 아닌 2개의 공백으로 하위 항목을 구분한다.
version: "3.0"
services:
app5221:
build:
context: /home/user5221
dockerfile: Dockerfile
container_name: app5221
ports:
- "5221:80"
volumes:
- 5221:/home/download
app5222:
build:
context: /home/user5222
dockerfile: Dockerfile
container_name: app5222
ports:
- "5222:80"
volumes:
- 5222:/home/download
app5224:
build:
context: /home/user5224
dockerfile: Dockerfile
container_name: app5224
ports:
- "5224:80"
volumes:
- 5224:/home/download
volumes:
'5221':
external: true
'5222':
external: true
'5224':
external: true
- version - Docker Compose 버전을 지정한다. 3.0 버전은 Docker Compose 1.10 및 Docker Engine 1.13.0 이상에서 사용된다.
- services - 생성될 컨테이너를 묶어놓은 단위로 services 아래에 생성할 컨테이너 서비스를 지정한다.
- app5221, app5222, app5224 - 생성될 서비스의 이름으로 각각의 서비스는 하나의 컨테이너를 나타낸다.
- build - build 아래에 하위 항목으로 빌드할 때 사용할 옵션을 지정한다.
- context
- Dockerfile이 있는 경로를 지정한다.
- 이전에 Dockerfile로 빌드 할 때
su - user5221
계정으로 접속해 루트 경로에서 Dockerfile과 app.jar을 두고 진행했었다. 현재 경로에서 dockerfile과 build 파일이 어디 있는지 적어주면 된다.
- dockerfile - Dockerfile 그대로 적어준다.
- context
- container_name - 컨테이너 명을 지정한다.
- ports
- 해당 컨테이너로 접속할 포트를 지정한다.
- 5221 포트로 요청 시 컨테이너 내부의 80 포트로 전달한다.
-
FROM openjdk:17-jdk-alpine ARG JAR_FILE=*.jar ADD ${JAR_FILE} app.jar EXPOSE 80 WORKDIR /home/user5221 VOLUME /home/download/ ENTRYPOINT ["java","-jar","-Dspring.profiles.active=prod","/app.jar"]
- 조금 더 쉽게 이해하기 위해 위의 dockerfile을 보자. dockerfile에 EXPOSE를 80으로 지정했다. 이것은 도커 컨테이너 내부에 포트 번호를 80으로 지정한다는 뜻이다. 그리고 docker-compose.yml에서 지정한 ports 5221은 내가
도메인:5221
로 접근할 경우 5221 포트를 확인하고 도커 컨테이너 내부의 80 포트로 매핑해주는 것이다.
- volumes - 호스트와 컨테이너 간의 디렉토리 혹은 파일을 공유할 수 있는 볼륨을 지정한다.(볼륨이 없다면
docker volume create --name ${볼륨명 }
으로 만들면 된다) 왼쪽엔 내가 만들어놨던 도커 볼륨을 오른쪽엔 컨테이너 내에 파일이 저장될 경로를 적어주면 된다.
- services - 생성될 컨테이너를 묶어놓은 단위로 services 아래에 생성할 컨테이너 서비스를 지정한다.
- volumes
- 외부 볼륨을 설정한다.
- 5221 ~ 5224 - 볼륨명(참고로 숫자만 있다면 따옴표(’)로 감싸줘야 한다. 아니면 docker-compose.yml 실행 시 따옴표로 감싸라며 에러가 발생한다)
- external: true - docker-compose.yml에서 정의한 볼륨이 외부에 이미 존재하며 Docker Compose가 해당 볼륨을 새로 생성하지 않고 기존에 있던 볼륨을 사용할 수 있도록 지정한다.
3. httpd 수정
❓ 앞에 숫자가 있는 것은 vi 편집기에서 `:set number` 명령어로 넘버 라인을 표시했기 때문이다.
47 Listen 80
100 ServerName localhost:80
360 <VirtualHost *:80>
361 ServerName ljy.r-e.kr
362 ProxyPreserveHost On
363 ProxyPass / http://192.168.56.103:5221/
364 ProxyPassReverse / http://192.168.56.103:5221/
365 </VirtualHost>
366
367 <VirtualHost *:80>
368 ServerName replay.o-r.kr
369 ProxyPreserveHost On
370 ProxyPass / http://192.168.56.103:5222/
371 ProxyPassReverse / http://192.168.56.103:5222/
372 </VirtualHost>
373
374 <VirtualHost *:80>
375 ServerName ttoganjip.kro.kr
376 ProxyPreserveHost On
377 ProxyPass / http://192.168.56.103:5224/
378 ProxyPassReverse / http://192.168.56.103:5224/
379 </VirtualHost>
- Listen 80 - 호스트 PC의 포트 번호는 기본적으로 80이다. 어디서 사용하는 거 아니면 변경할 필요는 없다.
- ServerName localhost:80 - ServerName에 앞에 #로 주석 처리가 되어있을 경우 'systemctl restart httpd' 했을 때 에러가 발생하므로 주석을 풀어준다.
- <VirtualHost> - 가상 호스트를 설정하는 시작 태그
- * - 와일드 카드, 모든 IP에서 접근할 수 있다.
- 80 - 웹 브라우저에서 접근할 포트
- ServerName - 발급받은 도메인 주소를 적어주면 된다.
- ProxyPass
- 웹 서버가 받은 요청을 다른 서버로 전달한다.
- 간단하게 설명하면
ljy.r-e.kr
도메인으로 접근할 경우 포트 80은 http의 기본 포트이기 때문에 생략이 가능하다. 그리고 ProxyPass 옆에/
로 명시했기 때문에 ServerName 자체로 접근이 가능하다. 만약/
옆에/app1
과 같이 문자가 있을 경우http://ljy.r-e.kr/app1
까지 접근해줘야 192.xxx.xxx.xx.xxx:5221 로 매핑된다. /
우측의192.xxx.xx.xxx
는 호스트 PC(도커 컨테이너가 있는 가상 서버)의 IP 주소이며5221
은 위에 docker-compose.yml을 실행하며 생성된 도커 컨테이너의 포트 번호이다.
- ProxyPassReverse - ProxyPassReverse는 ProxyPass로 전달된 요청의 응답을 원래 요청한 URL(http://ljy.r-e.kr)로 반환한다.
4. docker-compose.yml 실행
[root@localhost ~]# docker-compose up -d
Building app5221
Step 1/7 : FROM openjdk:17-jdk-alpine
17-jdk-alpine: Pulling from library/openjdk
Digest: sha256:4b6abae565492dbe9e7a894137c966a7485154238902f2f25e9dbd9784383d81
Status: Downloaded newer image for openjdk:17-jdk-alpine
---> 264c9bdce361
Step 2/7 : ARG JAR_FILE=*.jar
---> Running in d4e39d164dab
---> Removed intermediate container d4e39d164dab
---> 123f25dbf9ef
Step 3/7 : ADD ${JAR_FILE} app.jar
---> 3c33b3c3ab69
Step 4/7 : EXPOSE 80
---> Running in 2b4b2b2843d1
---> Removed intermediate container 2b4b2b2843d1
---> a5d5b704de06
Step 5/7 : WORKDIR /home/user5221
---> Running in 2e3190589b51
---> Removed intermediate container 2e3190589b51
---> de8bdb8b89a9
Step 6/7 : VOLUME /home/download/
---> Running in 8e8f719dee29
---> Removed intermediate container 8e8f719dee29
---> d1906f0955fd
Step 7/7 : ENTRYPOINT ["java","-jar","-Dspring.profiles.active=prod","/app.jar"]
---> Running in 76b283596830
---> Removed intermediate container 76b283596830
---> 45add8706680
Successfully built 45add8706680
Successfully tagged root_app5221:latest
Step 1/7 : FROM openjdk:17-jdk-alpine
---> 264c9bdce361
Step 2/7 : ARG JAR_FILE=*.jar
---> Using cache
---> 123f25dbf9ef
Step 3/7 : ADD ${JAR_FILE} app.jar
---> d82f9b2101cf
Step 4/7 : EXPOSE 80
---> Running in 5de73cff26e0
---> Removed intermediate container 5de73cff26e0
---> e882c553ce93
Step 5/7 : WORKDIR /home/user5222
---> Running in 1e8354ca8a60
---> Removed intermediate container 1e8354ca8a60
---> 0f4aa1023a3f
Step 6/7 : VOLUME /home/download/
---> Running in e960781f165a
---> Removed intermediate container e960781f165a
---> 865d83bf6c09
Step 7/7 : ENTRYPOINT ["java","-jar","-Dspring.profiles.active=prod","/app.jar"]
---> Running in 2b4961456f2e
---> Removed intermediate container 2b4961456f2e
---> 05a578f785fc
Successfully built 05a578f785fc
Successfully tagged root_app5222:latest
Step 1/7 : FROM openjdk:17-jdk-alpine
---> 264c9bdce361
Step 2/7 : ARG JAR_FILE=*.jar
---> Using cache
---> 123f25dbf9ef
Step 3/7 : ADD ${JAR_FILE} app.jar
---> 3320792a1923
Step 4/7 : EXPOSE 80
---> Running in cebb9be1f1f7
---> Removed intermediate container cebb9be1f1f7
---> d236bab3f5ae
Step 5/7 : WORKDIR /home/user5224
---> Running in b569d6082ae4
---> Removed intermediate container b569d6082ae4
---> 717ddfe785e0
Step 6/7 : VOLUME /home/download/
---> Running in afac756c4972
---> Removed intermediate container afac756c4972
---> b8509aceb6a7
Step 7/7 : ENTRYPOINT ["java","-jar","-Dspring.profiles.active=prod","/app.jar"]
---> Running in 85b6a4ae19c8
---> Removed intermediate container 85b6a4ae19c8
---> 27fa929132f9
Successfully built 27fa929132f9
Successfully tagged root_app5224:latest
Creating app5221
Creating app5224
Creating app5222
Creating apache
그리고 docker ps
명령어를 통해 컨테이너가 정상적으로 띄워졌는지 확인해보자.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e4475ce40736 root_app5221 "java -jar -Dspring.…" 3 hours ago Up 3 hours 0.0.0.0:5221->80/tcp, :::5221->80/tcp app5221
f344f94e5267 root_app5222 "java -jar -Dspring.…" 3 hours ago Up 3 hours 0.0.0.0:5222->80/tcp, :::5222->80/tcp app5222
bb9858deaf5f root_app5224 "java -jar -Dspring.…" 3 hours ago Up 3 hours 0.0.0.0:5224->80/tcp, :::5224->80/tcp app5224
925df5c890d9 mariadb "docker-entrypoint.s…" 8 days ago Up 2 days 0.0.0.0:3307->3306/tcp, :::3307->3306/tcp mariadb
5. 포트 포워딩 및 방화벽 포트 등록
1. 공유기 포트 포워딩
80 포트는 가상 서버의 httpd 기본 포트(변경하지 않았으므로 이 포트를 사용했다) 그리고 5221 ~ 5229까지 되어있는 것은 위에서 5221, 5222, 5224와 같이 도커 컨테이너 접근 시 사용하는 포트 번호를 미리 설정해놓은 것이다.
2. 가상 머신 포트 포워딩
내가 포스팅한 네트워크 관련 글에는 죄다 이 캡처가 들어가있는 것 같은데.. 여튼 이렇게 외부에서 들어오는 요청을 받을 수 있게 설정해준다. 외부에서 80 포트로 들어오면 내부의 80 포트(http 기본 포트)로 연결시킨다. 만약 httpd.conf에서 포트를 8080 뭐 이런 식으로 잡았다면 80, 8080으로 설정해야겠지..
3. 방화벽 포트 등록
80 포트를 받을 수 있게 firewall을 통해 포트를 등록한다.
[root@localhost ~]# firewall-cmd --permanent --add-port=80/tcp
[root@localhost ~]# firewall-cmd --reload
[root@localhost ~]# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: enp0s3 enp0s8
sources:
services: cockpit dhcpv6-client ssh
ports: 30000/tcp 80/tcp
protocols:
forward: yes
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
이렇게 등록되어 있으면 된다.
6. 도메인 등록
나는 무료로 도메인을 발급해주는 내도메인.한국을 사용하고 있다.
궁금하면 아래 이전 포스팅 링크를 통해 발급받는 방법을 확인할 수 있다.
[ETC] 무료 도메인 발급
포트폴리오, 실습용으로 도메인을 구입하기엔 치킨 한마리 값이라도 뭔가 비싸보였다. 그래서 무료 도메인 발급을 검색하다가 내도메인.한국 이라는 곳을 알게 되었는데 사용법을 검색하지 않
mytilblog.tistory.com
그리고 IP 연결할 때 뒤에 포트 번호는 붙이지 않는다.
공인 IP로 해당 도메인에 접근했을 때 위에 httpd.conf에서 지정한 5221 포트로 매핑된다.
7. 확인
짠~
'Network > Docker' 카테고리의 다른 글
[Network | Docker] jar 배포 (0) | 2024.07.07 |
---|---|
[Network | Docker] Dockerfile (0) | 2024.07.05 |
[Network | Docker] 이미지 (0) | 2024.07.04 |
[Network | Docker] 네트워크 (0) | 2024.07.03 |
[Network | Docker] 데이터베이스 외부 원격 접속 (0) | 2024.07.03 |