기존 서비스는 Windows 서버에서 JAR 파일을 직접 실행하는 방식으로 운영되고 있었다. 서버가 자주 불안정했고, Windows 환경 특성상 운영 자체가 불편한 점이 많았다. 결국 리뉴얼을 결정하면서 Linux + Docker 환경으로 전환하기로 했다.
전환을 준비하던 중 감사 일정이 잡혔다. 감사에서 가장 중요한 요구사항은 개인정보가 저장된 DB에 대한 접근 제한이었다.
요구사항을 정리하면:
서브넷은 하나의 네트워크를 더 작은 단위로 나눈 것이다. 쉽게 말하면 같은 건물 안에서도 층별로 독립된 내선 전화망을 구성하는 것과 비슷하다. 같은 층(서브넷) 안에서는 자유롭게 통신할 수 있지만, 다른 층(서브넷)과는 별도의 경로를 통해야 한다.
예를 들어 172.10.0.0/24 라는 서브넷은:
172.10.0.0 — 네트워크 주소/24 — 앞 24비트가 네트워크 대역, 나머지 8비트가 호스트 대역172.10.0.1 ~ 172.10.0.254 범위의 IP를 사용할 수 있음Docker는 컨테이너 간 통신을 위한 가상 네트워크를 직접 구성할 수 있다. 기본적으로 컨테이너를 실행하면 bridge 라는 기본 네트워크에 연결되는데, 이 경우 모든 컨테이너가 같은 네트워크에 있어 서로 통신이 가능하다.
커스텀 네트워크를 만들면:
전통적인 서버 환경에서 서브넷은 물리적인 네트워크 장비로 구성한다. 하지만 Docker는 소프트웨어적으로 가상 네트워크를 만들 수 있어서, 서브넷 개념을 컨테이너 레벨에서 그대로 구현할 수 있다.
즉 Docker 네트워크에 서브넷을 지정하면:
이 특성을 활용해서 외부에 노출할 서비스(API) 와 내부에서만 동작할 서비스(Batch, DB 등) 를 분리했다.
docker network create \
--driver bridge \
--subnet 172.10.0.0/24 \
--gateway 172.10.0.1 \
app-network
--driver bridge — 단일 호스트 내 컨테이너 간 통신--subnet — 네트워크 대역 지정--gateway — 게이트웨이 IP 지정각 컨테이너에 고정 IP를 부여했다. IP가 고정되어 있으면 컨테이너가 재시작되어도 IP가 유지되기 때문에 서비스 간 통신 설정이 흔들리지 않는다.
docker run \
--name app-api \
--network app-network \
--ip 172.10.0.11 \
...
| 컨테이너 | IP | 외부 노출 |
|---|---|---|
| nginx | - | ✅ |
| app-api | 172.10.0.11 | ❌ (nginx 통해서만) |
| app-a | 172.10.0.12 | ❌ |
| app-b | 172.10.0.13 | ❌ |
| app-mysql | 172.10.0.10 | ❌ |
기존 nginx 컨테이너가 있다면 app-network에 추가로 연결할 수 있다. nginx는 여러 네트워크에 동시에 연결될 수 있기 때문에 외부 네트워크와 app-network 사이의 리버스 프록시 역할을 할 수 있다.
docker network connect app-network nginx
외부 요청 흐름
외부 → nginx → app-api (172.10.0.11)
내부에서만 접근 가능
app-a (172.10.0.12)
app-b (172.10.0.13)
app-mysql (172.10.0.10)
DB는 app-network 내부에서만 접근 가능하기 때문에 외부에서 직접 접속할 수 없다. 반드시 서버에 SSH로 접속한 후 컨테이너를 통해 접근해야 한다.
# 서버 SSH 접속
ssh user@server-ip
# 컨테이너 진입 후 DB 접속
docker exec -it app-mysql bash
mysql -u root -p
처음에는 네트워크를 별도로 구성해야 한다는 게 번거롭게 느껴졌다. 그냥 포트를 열고 닫는 것만으로도 충분하지 않을까 싶었는데, 직접 구성해보니 생각보다 훨씬 명확하게 서비스를 격리할 수 있었다.
서브넷이라는 개념이 물리적인 네트워크 장비에서만 가능한 줄 알았는데, Docker에서 소프트웨어적으로 동일하게 구현할 수 있다는 게 인상적이었다.
다만 이 방식은 단일 호스트에서의 격리에 한정된다는 점을 염두에 두어야 한다. 서비스가 커지거나 멀티 호스트 환경이 필요해진다면 Docker 네트워크만으로는 한계가 있다. Kubernetes는 이런 네트워크 격리와 서비스 디스커버리를 훨씬 정교하게 다룰 수 있고, 실제로 이 부분이 Docker와 Kubernetes의 가장 큰 차이 중 하나라고 생각한다.
Docker 네트워크를 직접 구성해보면서 네트워크 격리의 개념을 이해할 수 있었고, 이게 Kubernetes에서는 어떻게 추상화되어 동작하는지 더 공부해보고 싶어졌다.