Infra/Docker

Docker Swarm 에 대해서...

minseoki 2026. 5. 5. 17:09

[Docker] Docker Swarm 정리

Docker를 사용하다 보면 단일 서버만으로는 한계가 생긴다. 트래픽이 몰리거나 서버가 죽었을 때 대응이 안 되기 때문이다. 이런 문제를 해결하기 위해 나온 게 바로 Docker Swarm이다.


Docker vs Docker Compose vs Docker Swarm

  • Docker — 단일 호스트, 단일 컨테이너
  • Docker Compose — 단일 호스트, 여러 종류의 컨테이너
  • Docker Swarm — 다수의 호스트(manager + workers)에 여러 종류의 컨테이너

여러 개의 호스트 묶음을 "클러스터" 라고 한다.
docker swarm은 도커에서 만든 컨테이너 오케스트레이션 툴이다.


오케스트레이션이란?

오케스트레이션은 다수의 호스트로 구성된 클러스터에서 다수의 컨테이너를 관리하는 기술이다. (스케일링, 헬스체크, 로드밸런서(트래픽제어))

혼자서 악기 하나를 연주하는 건 쉽지만, 수십 명의 연주자가 합주를 하려면 지휘자가 필요하다.

docker swarm은 그 지휘 역할을 하는 것이다.

  • 클러스터링 : 여러 대의 물리 서버를 하나의 가상 리소스로 통합한다.
  • 스케일링 : 명령 한 줄로 컨테이너 개수를 수십 개로 늘리거나 줄인다.
  • 상태 관리(Self-healing) : 어떤 서버가 죽어서 컨테이너가 꺼지면 살아있는 다른 서버에 자동으로 그 컨테이너를 다시 살려낸다.
  • 로드밸런싱(트래픽제어) : 들어오는 요청을 여러 서버에 떠 있는 컨테이너들에게 골고루 분산한다.

docker swarm 클러스터 구성

실습에서 사용한 클러스터 구성은 아래와 같다.

  • manager : 211.183.3.100
  • worker1 : 211.183.3.110
  • worker2 : 211.183.3.120

manager node 구성

manager 노드는 control plane 역할을 한다. manager에서 아래 명령으로 swarm을 초기화한다.

docker swarm init

초기화 후 출력되는 join 토큰을 파일로 저장해두자.

vi token

manager 노드와 worker1,2 노드가 연결이 되었다.


docker service

다수의 호스트에 한 가지 종류의 컨테이너를 한 개 이상 생성한다. docker run으로 컨테이너를 생성하는 것과 비슷한 개념이다.

docker service create --replicas 2 -p 5858:80 --name myweb oolralra/ipnginx

--replicas : 복제본, 컨테이너를 두 개 띄우겠다는 의미.

ipnginx : 자신(컨테이너)의 IP를 출력하는 이미지.

로드밸런싱이 잘 되고 있다.

docker service ps myweb

따로 컨테이너 배치 제한을 두지 않았기 때문에 현재 총 3개의 노드 중 아무 곳에 배치되었을 것이다.

docker network inspect ingress

docker swarm을 구성하는 순간, 오버레이 네트워크도 함께 구성된다.
오버레이 네트워크에 의해 다른 호스트에 있는 컨테이너들끼리도 서로 통신이 가능하다.

만든 web1과 web2 컨테이너를 하나로 묶어주는, 눈에는 보이지 않는 접속 포인트가 생긴다. (LB와 유사)


docker stack deploy

  • docker compose와 비슷하다. 컴포즈 파일이 필요하다.
  • 기존의 컴포즈 파일과 거의 문법이 흡사하지만 조금 다른 부분이 있다.

스택이란 여러 종류의 서비스의 묶음이라고 생각하면 된다.

mkdir /swarm
cd /swarm
vi docker-compose.yml
services:
  ip-nginx:
    image: oolralra/ipnginx
    deploy:
      replicas: 2
      placement:
        constraints: [node.role != manager]

노드의 역할이 manager인 경우는 배치하지 않겠다. 워커노드에만 컨테이너를 배치하겠다.

docker stack deploy -c docker-compose.yml ip-stack
docker stack rm ip-stack

스택 삭제 명령어.


visualizer — 컨테이너 시각화

각 호스트의 컨테이너를 시각화하는 컨테이너 이미지 = visualizer

vi visual.yml
services:
  visual:
    image: 61.254.18.30:5000/visualizer
    ports:
    - '5656:8080'
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock
    deploy:
      placement:
        constraints: [node.role == manager]
docker stack deploy -c visual.yml vis

insecure 설정이 안 되어있으면 해주자.

vi /etc/docker/daemon.json
{
        "insecure-registries": ["211.183.3.100:5000","61.254.18.30:5000"]
}
systemctl restart docker

211.183.3.100:5656으로 접속.


실습 1 — 사설 저장소에서 이미지 가져오기

61.254.18.30:5000/ipnginx:latest 이미지로 컴포즈 파일을 수정해서 replicas 4개로 5959 포트로 publish 해보자.

저장소 수정 후 insecure 설정도 바꿔줘야 한다.

사설 저장소에 이미지가 존재함에도 불구하고 컨테이너가 띄워지지 않는다.
사설 저장소 insecure 설정이 manager 노드에만 되어있는데, 실질적으로 컨테이너 이미지를 땡겨오는 주체는 worker1과 worker2이기 때문이다.
worker1과 worker2에도 insecure 설정을 해주면 된다.

vi /etc/docker/daemon.json
{
        "insecure-registries": ["211.183.3.100:5000","61.254.18.30:5000"]
}
docker stack deploy -c docker-compose.yml pstack

실습 2 — ECR 퍼블릭 갤러리 이미지로 WordPress + MySQL 스택 배포

DB는 manager에 한 개만 띄우고, wordpress는 worker 노드에 2개를 띄워서 12345 포트로 접속 가능하게 해보자.

vi wordpress.yml
services:
  mywp:
    image: public.ecr.aws/docker/library/wordpress:php8.1-apache
    ports: 
    - '12345:80'
    deploy:
      replicas: 2
      placement:
        constraints: [node.role == worker]
    environment:
      WORDPRESS_DB_HOST: dbdb
      WORDPRESS_DB_USER: wpuser
      WORDPRESS_DB_PASSWORD: '1234'
      WORDPRESS_DB_NAME: wpdb
    depends_on:
    - dbdb

  dbdb:
    image: public.ecr.aws/docker/library/mysql:8
    deploy:
      placement:
        constraints: [node.role == manager]
    environment:
    - MYSQL_ROOT_PASSWORD=1234
    - MYSQL_USER=wpuser
    - MYSQL_PASSWORD=1234
    - MYSQL_DATABASE=wpdb

잘 접속된다.