여러 Compose 파일을 사용하여 동일한 docker network에 동일한 서비스 이름의 다른 앱을 시작할 때의 동작

15549 단어 docker-compose도커

전제



아무도 신경 쓰지 않았을지도 모르지만 핀 포인트 정보를 찾을 수 없었기 때문에

동작 확인 환경



windows 10


서비스 이름



본 기사에서는, 이하에 나타내는 부분으로 지정한 명칭을 서비스명이라고 합니다

docker-compose.yml
version: '3.8'
services:
  srv1: # <- ここ!
    image: node:14

단일 Compose 파일의 경우



단일 Compose 파일에서 동일한 서비스 이름을 정의하면
나중에 정의된 쪽이 우선하며 동시에 시작되지 않습니다.

docker-compose.yml
version: '3.8'
services:
  srv1:
    image: node:14
    container_name: node14

  srv1:
    image: node:12
    container_name: node12

실행 결과
$ docker compose up
[+] Running 2/2
 ⠿ Network compose_demo_default  Created                                                  0.0s
 ⠿ Container node12              Started                                                  2.3s
Attaching to node12
node12 exited with code 0

여러 Compose 파일에서 동일한 docker network에 속합니다.



동일한 폴더 계층 구조의 여러 Compose 파일에서
같은 이름의 서비스를 시작하려고 할 때,
위와 같은 결과가 됩니다(나중에 compose up한 것에 Recreate된다)

따라서 Compose 파일을 다른 폴더에 넣거나,
런타임에 -p 옵션을 사용하여 별도의 프로젝트로 인식해야 합니다.

docker-compose.app1.yml
version: '3.8'
networks:
  default:
    name: local_link
services:
  srv1:
    image: nginx:latest
    container_name: app1

docker-compose.app2.yml
version: '3.8'
networks:
  default:
    name: local_link
services:
  srv1:
    image: nginx:latest
    container_name: app2

실행 결과
$ docker compose -p app1 -f docker-compose.app1.yml up -d
[+] Running 2/2
 ⠿ Network local_link  Created                                                              0.0s
 ⠿ Container app1      Started                                                              0.8s
$ docker compose -p app2 -f docker-compose.app2.yml up -d
[+] Running 1/1
 ⠿ Container app2  Started                                                                  0.9s

확인


docker network inspect 에서 확인

실행 결과
$ docker network inspect local_link
   (略)
        "Containers": {
            "09d61a2de...": {
                "Name": "app2",
                ...
            },
            "0cdf3f601...": {
                "Name": "app1",
                ...
            }
        },
  (略)

동일한 네트워크에 속합니다.
또한 각 컨테이너의 정보를 확인합니다.

inspect (app1)
$ docker inspect app1
  (略)
   "Networks": {
     "local_link": {
        "Aliases": [
           "app1",
           "srv1",
           "0cdf3f601f16"
        ],
  (略)

inspect (app2)
$ docker inspect app2
  (略)
   "Networks": {
     "local_link": {
        "Aliases": [
          "app2",
          "srv1",
          "09d61a2dea34"
        ],
  (略)

네트워크 별칭으로
  • 컨테이너 이름
  • 서비스 이름
  • 컨테이너 ID

  • 가 등록되어 있는 것을 알 수 있다.
    다른 앱에 동일한 서비스 이름이 등록된 이 상태에서
    srv1에 액세스하면 어떻게 될지가 이번 주제입니다.

    auto scale 이야기



    본제에 들어가기 전에,
    동일한 서비스 이름이 여러 컨테이너에 연결되는 것이 바람직한 상황으로
    스케일 아웃하고 싶은 경우가 생각됩니다.
    확인해 보면

    docker-compose.app1.yml
    version: '3.8'
    
    services:
      srv1:
        image: nginx:latest
        # container_name: app1 # コンテナ名はユニークなのでスケールさせる場合は指定できない
    
    networks:
      default:
        name: local_link
    

    실행 결과
    $ docker compose -p app1 -f docker-compose.app1.yml up -d --scale srv1=2
    [+] Running 3/3
     ⠿ Network local_link     Created                                       0.0s
     ⠿ Container app1_srv1_2  Started                                       0.8s
     ⠿ Container app1_srv1_1  Started                                       0.7s
    
    $ docker network inspect local_link
      (略)
      "Containers": {
        "5dd3a0844....": {
          "Name": "app1_srv1_2",
          ...
        },
        "d926584e....": {
          "Name": "app1_srv1_1",
          ...
        }
      },
    
    $ docker inspect app1_srv1_1
      (略)
       "Networks": {
         "local_link": {
            "Aliases": [
              "app1_srv1_1",
              "srv1",
              "d926584e7947"
            ],
      (略)
    
    $ docker inspect app1_srv1_2
      (略)
       "Networks": {
         "local_link": {
            "Aliases": [
              "app1_srv1_2",
              "srv1",
              "5dd3a08445a7"
            ],
      (略)
    

    (당연히 모르겠지만) 예상대로 동일한 서비스 이름으로 별칭이 등록됩니다.

    주제



    아래 설정에서 시작한 nginx에서 각각 액세스하십시오.

    docker-compose.yml
    version: '3.8'
    
    services:
      proxy:
        image: nginx:latest
        container_name: proxy
        volumes:
          - ./default.conf:/etc/nginx/conf.d/default.conf
        ports:
          - 8080:80
    
    networks:
      default:
        name: local_link
    
    

    default.conf
    server {
        listen       80;
        listen  [::]:80;
        server_name  localhost;
    
        location /app1/ {
          proxy_pass http://app1:8080/;
        }
    
        location /app2/ {
          proxy_pass http://app2:8080/;
        }
    
        location /srv1/ {
          proxy_pass http://srv1:8080/;
        }
    
        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }
    
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    
    }
    

    app1, app2



    이번에는 golang에서 만들었습니다.
    app1과 app2의 차이가 있는 부분은 동행에 코멘트로 적었습니다.

    main.go
    package main
    
    import (
        "fmt"
        "net/http"
    )
    
    func hello(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, from app1") // app2では Hello, from app2
    }
    
    func main(){
        http.HandleFunc("/", hello)
        http.ListenAndServe(":8080", nil)
    }
    

    Dockerfile
    FROM golang:1.16 AS build-env
    WORKDIR /app
    COPY . .
    RUN go get && go build -o serve.out
    
    FROM gcr.io/distroless/base
    WORKDIR /app
    COPY --from=build-env /app/serve.out .
    
    CMD ["./serve.out"]
    EXPOSE 8080
    

    docker-compose.yml
    version: '3.8'
    
    services:
      srv1:
        build:
          context: .
        image: app1:latest # app2:latest
        container_name: app1 # app2
    
    networks:
      default:
        name: local_link
    

    결과



    /app1/에 액세스


    /app2/에 액세스


    /srv1/에 액세스(첫 번째)


    /srv1/에 액세스(두 번째)


    auto scale의 이야기를 한 시점에서 어쩐지 예상할 수 있었지만,
    같은 서비스명의 컨테이너에 번갈아 액세스하고 있는 모양.
    스케일 했을 때의 로드 밸런싱의 사양을 조사하면, 어떻게 되어 있는지 알 수 있다고 생각합니다.

    결론



    다른 앱에 동일한 서비스 이름을 부여하고 동일한 네트워크에 배포하는 경우
    예기치 않은 액세스가 발생할 수 있습니다.

    사이고에게



    networks를 작성하는 방법에서 아래와 같이 name을 지정하면,
    external을 지정하지 않아도 Compose 외부에 정의되어 있는 network 찾아주고,
    up와 동시에 없으면 창조되고 down와 동시에 이용되지 않으면 삭제된다
    라는 발견이 있었다

    docker-compose.yml
    version: '3.8'
    networks:
      default:
        name: local_link
      tmpname:
        name: my-net1
    
    services:
      srv1:
        image: nginx:latest
        networks:
          - default
          - tmpname
    

    네트워크가 생성된 프로젝트에 연결되기 때문에,
    지우는 순서에 따라 네트워크 만 사라지지 않고 남아있을 수 있으므로주의
    (다시 down하면 사라지므로 큰 문제는 아니지만)

    좋은 웹페이지 즐겨찾기