
WordPress 설치 및 몇 가지 웹 앱과 같은 다양한 서비스가 포함된 작은 VPS가 하나 있습니다. 한동안 저는 모든 서비스를 Docker 컨테이너로 실행했습니다. 이 상자를 가리키는 다양한 도메인과 하위 도메인이 있으므로 프런트엔드 프록시 Traefik을 사용하여 웹 포트를 캡처한 다음 Docker 네트워크에서 내부적으로 라우팅합니다.
나는 Traefik을 다음과 같이 시작합니다:
#!/bin/bash
# Removes the restart policy from previous containers
CONTAINER_LABEL=traefik-instance
../../bin/remove-restart.sh $CONTAINER_LABEL
mkdir --parents /var/log/traefik
mkdir --parents /etc/letsencrypt-traefik
docker run \
--label $CONTAINER_LABEL \
--publish 80:80 \
--publish 443:443 \
--volume $PWD/traefik.toml:/etc/traefik/traefik.toml \
--volume $PWD/rules:/etc/traefik/rules \
--volume /etc/letsencrypt-traefik:/etc/letsencrypt-traefik \
--volume /var/log/traefik:/log \
--network dockernet \
--detach \
--restart always \
traefik:1.6
이 모든 것이 매우 잘 작동합니다. 저는 최근 Docker Swarm을 발견했으며 모든 컨테이너를 서비스로 변환하여 복제 서비스, 롤링 업데이트 및 가동 중지 시간 없는 배포를 제공하려고 합니다. 그러나 Traefik이 Swarm 서비스와 일반(Swarm이 아닌) 컨테이너 모두로 라우팅할 수 있도록 단편적으로 변경하고 싶습니다.
그래서 Traefik을 서비스로 출시하기 위해 지금은 다음과 같은 작업을 하고 있습니다. 테스트 목적으로 비표준 포트를 사용하고 있음을 알 수 있습니다.
#!/bin/bash
# Using "traefik2" while I am experimenting with multiple services
mkdir --parents /var/log/traefik2
mkdir --parents /etc/letsencrypt-traefik
docker service create \
--publish 8080:80 \
--publish 8443:443 \
--mount type=bind,source=$PWD/traefik.toml,target=/etc/traefik/traefik.toml \
--mount type=bind,source=$PWD/rules,target=/etc/traefik/rules \
--mount type=bind,source=/etc/letsencrypt-traefik,target=/etc/letsencrypt-traefik \
--mount type=bind,source=/var/log/traefik2,target=/log \
--network traefiknet \
traefik:1.6
이는 동일한 네트워크에 나타나는 Swarm 웹 서비스를 가리킬 때도 작동합니다.
따라서 다음과 같은 두 개의 Docker 네트워크(Docker가 자체적으로 생성하는 다양한 기본값 중에서)가 있습니다.
root@box:~/docker# docker network ls
NETWORK ID NAME DRIVER SCOPE
1aa479f13faa dockernet bridge local
k71hpg1n0lo9 traefiknet overlay swarm
그 결과 Docker 컨테이너를 볼 수 있는 Traefik 컨테이너가 작동하고 Swarm 서비스를 볼 수 있는 Traefik 서비스가 작동하게 됩니다. 그러나 그들은 서로를 볼 수 없습니다.
이 문제를 해결하기 위해 Traefik Swarm 서비스 시작에 Docker 네트워크를 추가하려고 했습니다.
--network dockernet \
즉, 이 서비스가 브리지(기존) 네트워크와 오버레이(새) 네트워크 모두에 연결되기를 원합니다. 불행하게도 나는 이것을 얻습니다:
데몬의 오류 응답: 네트워크 Dockernet을 서비스와 함께 사용할 수 없습니다. 오버레이 드라이버로 생성된 것과 같이 떼로 범위가 지정된 네트워크만 사용할 수 있습니다.
새 서비스를 기존 네트워크에 연결할 수 있는 방법이 있나요? 아니면 실제로 기존 컨테이너를 새 네트워크에 연결할 수 있는 방법이 있나요? 해당 오류에 대해 검색해 보았지만 이에 대한 언급이 전혀 없는 것 같습니다. Swarm의 이러한 극단적인 사용이 아직 많은 사람들에 의해 접해본 적이 없는지 궁금합니다.
(물론 한 가지 해결책은 모든 컨테이너를 서비스로 변환하는 것이지만, 큰 변화를 피하기 위해 가능하면 천천히 수행하는 것이 좋습니다.)
연결 가능한 네트워크 사용해 보기
그런 다음 서비스를 삭제하고 다음을 시도했습니다.
docker network rm traefiknet
docker network create driver=overlay --attachable traefiknet
그런 다음 Traefik 서비스를 다시 만들고 시작했습니다. traefiknet 오버레이에 합류한 서비스로 트래픽을 라우팅하기 때문에 여전히 작동하고 있는 것이 분명합니다.
그러나 서비스가 아닌 컨테이너를 만들어서 에만 연결했는데 traefiknet
, --network-alias
내가 만든 컨테이너는 서비스에서 볼 수 없습니다. 이상하게도 Swarm이 아닌 컨테이너에 넣으면~할 수 있다Swarm Traefik 컨테이너를 핑하면 네트워크가 작동합니다. (Alpine 셸 서비스를 생성하고 에 연결하려고 시도했지만 traefiknet
여기서는 Swarm이 아닌 컨테이너의 컨테이너 이름이나 ping을 실행할 수 없습니다 --network-alias
.)
도커 업그레이드
Docker를 17.03.2-ce에서 18.06.1-ce로 업그레이드하려고 했습니다.설명서에내 이전 Docker 버전이 문제의 원인일 수 있다고 표시했습니다.
컨테이너와 스웜 서비스 간 통신은 연결 가능한 오버레이 네트워크를 사용하여 독립형 컨테이너와 스웜 서비스 간의 통신을 설정합니다. 이는 Docker 17.06 이상에서 지원됩니다.
그러나 이것도 도움이 되지 않았습니다.
답변1
나는 이 문제에 대한 해결책이 있다고 생각합니다. 하지만 여전히 이해하지 못하는 부분이 있습니다. 이 답변에 대한 컨텍스트를 설정하기 위해 Docker 비 Swarm 컨테이너를 설치하는 방법은 다음과 같습니다.
#!/bin/bash
# Save pwd and then change dir to the project root
STARTDIR=`pwd`
cd `dirname $0`/../..
# Removes the restart policy from previous containers
CONTAINER_LABEL=ilovephp-staging
NETWORK_ALIAS=${CONTAINER_LABEL}
./bin/remove-restart.sh $CONTAINER_LABEL
docker run \
--network swarmnet \
--network-alias ${NETWORK_ALIAS} \
--env TUTORIAL_ENVIRONMENT_NAME=staging \
--detach \
--restart always \
ilovephp:2018-08-19
# Go back to original dir
cd $STARTDIR
보시다시피, 제 질문 업데이트에 따라 이제 연결 가능한 Swarm 네트워크에 컨테이너를 배치할 수 있습니다.
Swarm 서비스에서 핑을 보낼 수 없는 이유는 --name
. 을 추가하자마자 --name
도달 가능해졌습니다. 하지만 흥미롭게도 Docker 컨테이너에서 Swarm 서비스나 Swarm 컨테이너를 ping하려고 하면 작동합니다.
root@server:~# docker exec -it loving_allen sh
/ # # *** Ping a specific Swarm container ***
/ # ping alpine-swarm.1.9llv2hvv5xnc1c8diuhfh5m09
PING alpine-swarm.1.9llv2hvv5xnc1c8diuhfh5m09 (10.0.1.23): 56 data bytes
64 bytes from 10.0.1.23: seq=0 ttl=64 time=0.516 ms
^C
--- alpine-swarm.1.9llv2hvv5xnc1c8diuhfh5m09 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.516/0.516/0.516 ms
/ # # *** Ping the Swarm service ***
/ # ping alpine-swarm
PING alpine-swarm (10.0.1.22): 56 data bytes
64 bytes from 10.0.1.22: seq=0 ttl=64 time=0.376 ms
^C
--- alpine-swarm ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.137/0.231/0.376 ms
따라서 원래 계획은 Traefik 인스턴스를 컨테이너에서 Swarm 서비스로 변환하는 것이었지만 이름이 지정되지 않은 Swarm 컨테이너가 아닌 컨테이너에는 연결할 수 없기 때문에 작동하지 않습니다. 이제 내 솔루션은 모든 시스템을 컨테이너에서 서비스로 먼저 변환한 다음 모든 작업이 완료되면 Traefik 인스턴스를 마지막으로 변환할 수 있습니다. 그렇게 하면 항상 컨테이너에서 서비스로 연결되며 그 반대는 아닙니다.
( --name
Docker 호스트가 다시 시작되면 동일한 이름의 컨테이너를 다시 생성하려고 시도하고 이전 컨테이너에 여전히 충돌하는 이름이 있기 때문에 s를 추가할 수 없습니다. 그리고 --rm
이를 수정하는 데 사용할 수 없습니다. 왜냐하면 와 호환되지 않습니다 --restart
!자세한 내용은 여기에서 확인하세요).
Docker가 생성한 컨테이너 이름이 Swarm 컨테이너에서 ping이 불가능한 이유와 a가 --network-alias
도움이 되지 않는 이유를 아직도 이해하지 못합니다. 그러나 내 솔루션은 모든 시스템이 Swarm 서비스가 될 때까지 임시적이어야 한다는 점을 고려하면 아마도 중요하지 않을 것입니다.