1. 개요

Docker 컨테이너를 실행하면 IP 주소를 사용하여 가상 네트워크에 연결됩니다. 이러한 이유로 우리는 서비스가 구성을 동적으로 가져오기를 기대합니다. 그러나 자동 IP 할당 대신 고정 IP를 사용하고 싶을 수도 있습니다.

이 사용방법(예제)에서는 기본 제공 구성과 컨테이너에 수동 IP를 할당하는 것의 차이점을 확인합니다. 마지막으로 테스트와 함께 몇 가지 Docker Compose 예제를 추가합니다.

2. DHCP 및 DNS

DHCP 및 DNS를 사용하여 호스트 이름을 확인하는 컨테이너에 대한 Docker 기본 제공 IP 할당을 살펴보겠습니다 .

2.1. Docker가 IP를 할당하는 방법

Docker는 먼저 DHCP 서버 역할을 하는 각 컨테이너에 IP 를 할당합니다. 또한 여러 DNS 서버가 있습니다.

그런 다음 컨테이너 는 동일한 내부 네트워크에 있는 다른 컨테이너의 이름을 인식하는 dockerd 내부의 서버로 DNS 요청을 처리합니다 . 이러한 방식으로 컨테이너는 내부 IP 주소를 몰라도 통신할 수 있습니다. 애플리케이션이 시작될 때마다 내부 IP 주소가 다를 수 있지만 컨테이너는 여전히 dockerd 내부의 내부 DNS 서버 덕분에 사람이 읽을 수 있는 이름으로 쉽게 연결할 수 있습니다 .

그런 다음 dockerd 는 이름 조회를 CNCF  에서  CoreDNS 로 보냅니다 . 마지막으로 요청은 도메인 이름에 따라 호스트로 이동합니다.

도메인 docker.internal 에 대한 측면 사례가 있습니다 . 여기에는 현재 호스트의 유효한 IP 주소로 확인되는 DNS 이름 host.docker.internal 이 포함됩니다. 이를 통해 컨테이너는 하드코딩 IP 주소에 대한 걱정 없이 해당 호스트 서비스에 연결할 수 있습니다. 권장되지는 않지만 개발 목적으로 유용할 수 있습니다.

2.2. 네트워크 예

예를 들어 MySQL 서비스용 컨테이너를 실행할 수 있습니다. Docker Compose YAML 정의 를 확인해 보겠습니다 .

services:
  db:
    image: mysql:latest
    environment:
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_ROOT_HOST=localhost
    ports:
      - 3306:3306
    volumes:
      - db:/var/lib/mysql
    networks:
      - network

volumes:
  db:
    driver: local

networks:
  network:
    driver: bridge

평소와 같이 컨테이너를 실행합니다.

docker-compose up -d

JSON 출력을 얻기 위해 jq 를 사용하는 형식 구문을 사용하여 컨테이너 관점에서 네트워크를 검사해 보겠습니다 .

docker inspect --format='{{json .NetworkSettings.Networks}}' 2d3f4c69a213 | jq .

Docker Compose는 현재 디렉터리를 기반으로 네트워크 이름을 할당합니다. 예를 들어 프로젝트 디렉토리에 있는 경우 유사한 출력을 볼 수 있습니다.

{
  "project_network": {
    "IPAMConfig": null,
    "Links": null,
    "Aliases": [
      "project-db-1",
      "db",
      "2d3f4c69a213"
    ],
    "NetworkID": "39ffbd8155d11ba03d0b548307f549f06790fe045e121a6d862b070d4fb67fa7",
    "EndpointID": "0eba235239b06f7e0cb5065b7f2ebd83e7d227f8cfad4df8de73260472737500",
    "Gateway": "172.19.0.1",
    "IPAddress": "172.19.0.2",
    "IPPrefixLen": 16,
    "IPv6Gateway": "",
    "GlobalIPv6Address": "",
    "GlobalIPv6PrefixLen": 0,
    "MacAddress": "02:42:ac:13:00:02",
    "DriverOpts": null
  }
}

컨테이너는 네트워크에서 생성된 서브넷에서 사설 172.19.0.2 IP 주소를 가져옵니다.

가장 중요한 것은 IP 주소 관리인 IPAMConfig 에 대한 정보를 볼 수 있다는 것입니다. IP를 정적으로 할당할 때 관련이 있습니다.

이제 네트워크를 검사할 수 있습니다.

docker inspect network project_network

이번에는 네트워크에 대한 더 나은 통찰력을 얻었습니다.

[
    {
        "Name": "project_network",
        "Id": "39ffbd8155d11ba03d0b548307f549f06790fe045e121a6d862b070d4fb67fa7",
        "Created": "2022-09-09T16:19:26.27396468+02:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.19.0.0/16",
                    "Gateway": "172.19.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "2d3f4c69a2139dea9089a6d42907fdc085282c5df176b39bf7c20f5d0780179d": {
                "Name": "project-db-1",
                "EndpointID": "7447fe2550afb3f980f36449673724e9ed6dd16f41a085cc20ada3074a0d8e54",
                "MacAddress": "02:42:ac:13:00:02",
                "IPv4Address": "172.19.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {
            "com.docker.compose.network": "network",
            "com.docker.compose.project": "project",
            "com.docker.compose.version": "2.10.2"
        }
    }
]

Docker Compose 네트워크 는 버전 2부터 사용할 수 있습니다.

3. 고정 IP

자동 IP 할당에 대해 조금 더 알고 있으므로 이제 네트워크의 서브넷을 생성합니다. 그런 다음 원하는 IP를 서비스에 할당할 수 있습니다.

3.1. 고정 IP 할당

Docker CLI를 사용하는 경우 먼저 서브넷을 생성하여 이 결과를 얻을 수 있습니다.

docker network create --subnet=10.5.0.0/16 mynet

그런 다음 정적 IP로 컨테이너를 실행하고 다시 MySQL 서비스로 실행합니다.

docker run --net mynet --ip 10.5.0.1 -p 3306:3306 --mount source=db,target=/var/lib/mysql -e MYSQL_ROOT_PASSWORD=password mysql:latest

Docker Compose를 사용하여 전체 예제를 마무리할 수 있습니다.

services:
  db:
    container_name: mysql_db
    image: mysql:latest
    environment:
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_ROOT_HOST=10.5.0.1
    ports:
      - 3306:3306
    volumes:
      - db:/var/lib/mysql
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      network:
        ipv4_address: 10.5.0.5

volumes:
  db:
    driver: local

networks:
  network:
    driver: bridge
    ipam:
      config:
        - subnet: 10.5.0.0/16
          gateway: 10.5.0.1

이제 ipam 키워드로 네트워크 의 서브넷을 정의하고 IPv4 주소를 서비스에 할당했습니다. 변경을 위해 10.5.0.5 를 사용했습니다 . 172.* 및 10.* IP 주소는 일반적으로 사설 네트워크에 사용됩니다. 또한 주소 길이가 128비트인 IPv6 주소 를 사용할 수 있으며 효율성 향상으로 인해 IPv4를 대체할 것입니다.

권장되는 대로 게이트웨이 주소를 데이터베이스 호스트 MYSQL_ROOT_HOST 에 할당합니다 .

마지막으로 SQL 스크립트를 추가하여 사용자, 데이터베이스 및 테이블을 생성합니다.

CREATE DATABASE IF NOT EXISTS test;
CREATE USER 'db_user'@'10.5.0.1' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'db_user'@'10.5.0.1' WITH GRANT OPTION;
FLUSH PRIVILEGES;

use test;

CREATE TABLE IF NOT EXISTS TEST_TABLE (id int, name varchar(255));

INSERT INTO TEST_TABLE VALUES (1, 'TEST_1');
INSERT INTO TEST_TABLE VALUES (2, 'TEST_2');
INSERT INTO TEST_TABLE VALUES (3, 'TEST_3');

우리는 사용자에게 해당 특정 주소에서만 데이터베이스에 대한 액세스 권한을 부여하려고 합니다.

컨테이너가 시작된 후 docker ps 로 정의를 볼 수 있습니다 .

CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS                                                  NAMES
97812e199512   mysql:latest   "docker-entrypoint.s…"   7 minutes ago   Up 7 minutes   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql_db

이제 암호를 입력하여 데이터베이스에 연결할 수 있습니다. DNS의 별칭으로 확인되므로 컨테이너 이름 또는 ID를 사용합니다.

mysql --host=mysql_db -u db_user -p

이제 status 명령을 사용하여 MySQL 호스트가 컨테이너 ID로 확인되는지 테스트할 수 있습니다.

Connection id:          10
Current database:       test
Current user:           db_user@10.5.0.1
SSL:                    Not in use
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server:                 MySQL
Server version:         8.0.30 MySQL Community Server - GPL
Protocol version:       10
Connection:             97812e199512 via TCP/IP
Server characterset:    utf8mb4
Db     characterset:    utf8mb4
Client characterset:    utf8mb3
Conn.  characterset:    utf8mb3
TCP port:               3306

3.2. 기본 제공 Docker IP 관리와의 차이점

컨테이너를 살펴보겠습니다. 정적 IP의 경우 이제 IPAM 구성에 IPv4 주소가 있음을 알 수 있습니다.

{
  "project_network": {
    "IPAMConfig": {
      "IPv4Address": "10.5.0.5"
    },
    "Links": null,
    "Aliases": [
      "project_db",
      "db",
      "122c0c6bfcf9"
    ],
    "NetworkID": "7ac7a1d9e33dffc65bc867aee4db04b9b8fecaeb3bbb91c74c2f72e4611c6955",
    "EndpointID": "84145191a0327b777b6a31bacb2a0260d9a31e8c22cbfca1923775b3649b1d7e",
    "Gateway": "10.5.0.1",
    "IPAddress": "10.5.0.5",
    "IPPrefixLen": 16,
    "IPv6Gateway": "",
    "GlobalIPv6Address": "",
    "GlobalIPv6PrefixLen": 0,
    "MacAddress": "02:42:0a:05:00:05",
    "DriverOpts": null
  }
}

컨테이너 관점에서 볼 때 이것이 주요 차이점입니다.

정적 개인 IP 주소가 필요한 경우 하나를 사용해야 하는지 고려해야 합니다. 대부분의 경우 고정 IP가 다른 컨테이너 또는 호스트에서 한 컨테이너와 통신하기를 원합니다. Docker의 기본 제공 네트워킹은 이미 이를 처리할 수 있습니다.

그러나 예를 들어 호스트에서 직접 컨테이너에 액세스하기 위해 사설 IP 주소를 수동으로 지정해야 할 수 있습니다.

Docker Swarm 을 사용한 사용자 지정 네트워킹의 가능성에 주목할 가치가 있습니다.

4. 결론

이 기사에서는 Docker가 IP 할당을 관리하는 방법과 컨테이너에 정적 주소를 추가하는 방법을 살펴보았습니다. 고정 IP를 사용하거나 사용하지 않고 MySQL 서비스를 실행하는 Docker Compose 구성의 예도 보았습니다.

항상 그렇듯이 GitHub에서 작업 코드 예제를 찾을 수 있습니다 .

Generic footer banner