ドッキングネットワーク


ドッキングステーションを使用してプロジェクトを行う場合、コンテナ間で通信する必要があるか、コンテナとホスト間で通信する必要があります.この文章では,これらの問題を解決できるドッキングステーションネットワークについてまとめる.

ドッキングステーションとコンテナの通信


ノードは、コンテナとコンテナの接続をテストするために使用されます.jsサーバをドッキングコンテナに配置し、redisイメージを受信し、ドッキングコンテナを作成すると、両方のコンテナを接続しようとします.
コンテナとコンテナを接続する方法は2つあります.
1つ目はコンテナのIPアドレス接続方式,2つ目はドックネットワーク方式である.
1つ目の方法は可能ですが、実際に使用する方法ではありません.まず最初の方法を適用し、なぜこの方法を使用しないのかを見てみましょう.

コンテナ継手疲労接続


コンテナの準備


まずredis画像からコンテナを作成します.
dong@ubuntu:~$ docker run --name redis-container -d redis
f1be3ac60962e647a9a7ca13e44d715f4e93613a0dec77253a4b2bf85db1a855
次にDockerfileを使用してノードサーバを解放します.
FROM node

WORKDIR /app

COPY package.json /app

RUN npm install

COPY . /app

EXPOSE 80

CMD ["node", "server.js"]
{
  "name": "docker-network-test",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "author": "dong",
  "license": "MIT",
  "dependencies": {
    "express": "^4.17.3",
    "body-parser": "^1.19.1",
    "redis": "^4.0.4"
  }
}
dong@ubuntu:~/docker-complete/DOCKER-NETWORK$ docker build . -t network-test-server

dong@ubuntu:~/docker-complete/DOCKER-NETWORK$ docker run -d -p 5000:80 -v "$(pwd)"/server.js:/app/server.js network-test-server
29b427768a4005e5055f8423184944153ac27593db5f7310e42ea79523df8e41
server.jsファイルをテストしbind mountにバインドして変更します.

Redis容器検査

docker container inspect {컨테이너명}を使用して、コンテナに関する情報を表示します.
dong@ubuntu:~/docker-complete/DOCKER-NETWORK$ docker container inspect redis-container
[
    {
        "Id": "f1be3ac60962e647a9a7ca13e44d715f4e93613a0dec77253a4b2bf85db1a855",
        "Created": "2022-03-13T17:20:01.08298854Z",
        "Path": "docker-entrypoint.sh",
        "Args": [
            "redis-server"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 9537,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2022-03-13T18:20:33.386639484Z",
            "FinishedAt": "2022-03-13T11:06:01.446890949-07:00"
        },
        "Image": "sha256:0e403e3816e890f6edc35de653396a5f379084e5ee6673a7608def32caec6c90",
        "ResolvConfPath": "/var/lib/docker/containers/f1be3ac60962e647a9a7ca13e44d715f4e93613a0dec77253a4b2bf85db1a855/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/f1be3ac60962e647a9a7ca13e44d715f4e93613a0dec77253a4b2bf85db1a855/hostname",
        "HostsPath": "/var/lib/docker/containers/f1be3ac60962e647a9a7ca13e44d715f4e93613a0dec77253a4b2bf85db1a855/hosts",
        "LogPath": "/var/lib/docker/containers/f1be3ac60962e647a9a7ca13e44d715f4e93613a0dec77253a4b2bf85db1a855/f1be3ac60962e647a9a7ca13e44d715f4e93613a0dec77253a4b2bf85db1a855-json.log",
        "Name": "/redis-container",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "docker-default",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "default",
            "PortBindings": {},
            "RestartPolicy": {
                "Name": "no",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "CapAdd": null,
            "CapDrop": null,
            "CgroupnsMode": "host",
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "private",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "ConsoleSize": [
                0,
                0
            ],
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": [],
            "BlkioDeviceReadBps": null,
            "BlkioDeviceWriteBps": null,
            "BlkioDeviceReadIOps": null,
            "BlkioDeviceWriteIOps": null,
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DeviceRequests": null,
            "KernelMemory": 0,
            "KernelMemoryTCP": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": null,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "MaskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware"
            ],
            "ReadonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        },
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/b2cb7c79ecd4732d45cc99330eb307be6aadc676b3172f362f0acc0d5570b7b4-init/diff:/var/lib/docker/overlay2/422fbddccc1421ff26e9493181e3a35610dbc297cf18a0f0a43d89380bc6ab04/diff:/var/lib/docker/overlay2/3197b0054d7f0fc61cd151104c844b76429a0799a711889f963e257a6c7ef393/diff:/var/lib/docker/overlay2/c2704b37ba2a2ccca54524c124d4c0691de9375c296b8612cc1458793cf68078/diff:/var/lib/docker/overlay2/90fc266e8ed171e5652db0798cccd23cde4ae351c36989c213724b544fcd3418/diff:/var/lib/docker/overlay2/2716ec58affdb467db15467e76a3b251d7571760c66cc1221cfbda10760512b1/diff:/var/lib/docker/overlay2/ce282d510bf3679c3f7453d85226c8cdeebc815562a5345701323cf5dedf0d55/diff",
                "MergedDir": "/var/lib/docker/overlay2/b2cb7c79ecd4732d45cc99330eb307be6aadc676b3172f362f0acc0d5570b7b4/merged",
                "UpperDir": "/var/lib/docker/overlay2/b2cb7c79ecd4732d45cc99330eb307be6aadc676b3172f362f0acc0d5570b7b4/diff",
                "WorkDir": "/var/lib/docker/overlay2/b2cb7c79ecd4732d45cc99330eb307be6aadc676b3172f362f0acc0d5570b7b4/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [
            {
                "Type": "volume",
                "Name": "16a5a7e47d184c9d712a49704810cb4a0a9d2f745c49a070df353b07d86cfe08",
                "Source": "/var/lib/docker/volumes/16a5a7e47d184c9d712a49704810cb4a0a9d2f745c49a070df353b07d86cfe08/_data",
                "Destination": "/data",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
        "Config": {
            "Hostname": "f1be3ac60962",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "6379/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "GOSU_VERSION=1.14",
                "REDIS_VERSION=6.2.6",
                "REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.2.6.tar.gz",
                "REDIS_DOWNLOAD_SHA=5b2b8b7a50111ef395bf1c1d5be11e6e167ac018125055daa8b5c2317ae131ab"
            ],
            "Cmd": [
                "redis-server"
            ],
            "Image": "redis",
            "Volumes": {
                "/data": {}
            },
            "WorkingDir": "/data",
            "Entrypoint": [
                "docker-entrypoint.sh"
            ],
            "OnBuild": null,
            "Labels": {}
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "c8f56c09c89f3b3be084a9ade541b941d5c2a1b1ccb8972e378b98763898cbda",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {
                "6379/tcp": null
            },
            "SandboxKey": "/var/run/docker/netns/c8f56c09c89f",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "a6f8dafde78b83c5fd53ab128eb22b7ee71df106dc84573254cb95e9224e504f",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.3",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:03",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "d0cee92cbfa0b81b614c3107757739bb2e1d6007f22e4e68c6e7274b8230b593",
                    "EndpointID": "a6f8dafde78b83c5fd53ab128eb22b7ee71df106dc84573254cb95e9224e504f",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.3",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:03",
                    "DriverOpts": null
                }
            }
        }
    }
]
コンテナ間の通信を可能にする2つのIPAddressが表示されます.
次のサーバーです.jsのコードから、redisを介して本IPAddress 172.17.0.3に接続されていることがわかる.
const express = require('express');
const bodyParser = require('body-parser');
const redis = require('redis');

const app = express();

const client = redis.createClient({
  url: 'redis://172.17.0.3:6379'
});

client.connect();

client.on('connect', () => console.log('Redis Client Connected'));
client.on('error', (err) => console.log('Redis Client Connection Error', err));

let userGoal = 'Enter Your Goal';

app.use(
  bodyParser.urlencoded({
    extended: false,
  })
);

app.use(express.static('public'));

app.get('/', (req, res) => {
  res.send(`
    <html>
      <head>
        <link rel="stylesheet" href="styles.css">
      </head>
      <body>
        <section>
          <h2>My Course Goal</h2>
          <h3>${userGoal}</h3>
        </section>
        <form action="/store-goal" method="POST">
          <div class="form-control">
            <label>Course Goal</label>
            <input type="text" name="goal">
          </div>
          <button>Set Course Goal</button>
        </form>
      </body>
    </html>
  `);
});

app.post('/store-goal', async (req, res) => {
  const enteredGoal = req.body.goal;
  
  await client.set("userGoal", enteredGoal);
  userGoal = await client.get("userGoal");
  res.redirect('/');
});

app.listen(80);


Reddisから正確な価格が得られたことが確認できます.
上記の方法には大きな問題があります.これは、redisコンテナが終了して再起動すると、ipoアドレスが変更される可能性があります.この理由でIPアドレスが変更された場合、Reddisコンテナを再度チェックし、IP、nodeをチェックします.jsコードを変更する必要がありますが、これは決して私たちが望んでいる方法ではありません.
したがって,我々が実際に用いている方法はドッキングステーションネットワークを用いる方法である.

ドッキングネットワークの使用


まず、docker network createコマンドを使用してドッキングネットワークを生成することができる.
dong@ubuntu:~/docker-complete/DOCKER-NETWORK$ docker network create test
953b4b4c3cf864443e7b20b89979356e6618e6e3dab4649bf8043677ba777be8
生成されたネットワークは、docker network lsコマンドを使用して検証することができる.
dong@ubuntu:~/docker-complete/DOCKER-NETWORK$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
d0cee92cbfa0   bridge    bridge    local
139bd915554d   host      host      local
f23aec4c0496   none      null      local
953b4b4c3cf8   test      bridge    local
testネットワークはbirdge障害ドライバbridgeによって生成され、ドライバについては後で再整理します.docker network connect Kmanを使用してコンテナをネットワークに接続できます.
# test 네트워크에 tender_murdock 컨테이너를 추가
dong@ubuntu:~/docker-complete/DOCKER-NETWORK$ docker network connect test tender_murdock
docker network inspectコマンドを使用して、ネットワークにコンテナが追加されていることを確認します.
dong@ubuntu:~/docker-complete/DOCKER-NETWORK$ docker network inspect test 
[
    {
        "Name": "test",
        "Id": "953b4b4c3cf864443e7b20b89979356e6618e6e3dab4649bf8043677ba777be8",
        "Created": "2022-03-13T12:17:26.854970604-07:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "7c23de714d1949464b78d3a9e828095af1e5f5fc003c70490fbf2f63dc4f95c2": {
                "Name": "tender_murdock",
                "EndpointID": "4bfd68b665c36d61e11af4171b27442f65149cb31ac24bdb7a44b00d4c808c17",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
redisを実行するredis-conainerもテストネットワークに追加されます.
dong@ubuntu:~/docker-complete/DOCKER-NETWORK$ docker network connect test redis-container
dong@ubuntu:~/docker-complete/DOCKER-NETWORK$ docker network inspect test
[
    {
        "Name": "test",
        "Id": "953b4b4c3cf864443e7b20b89979356e6618e6e3dab4649bf8043677ba777be8",
        "Created": "2022-03-13T12:17:26.854970604-07:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "7c23de714d1949464b78d3a9e828095af1e5f5fc003c70490fbf2f63dc4f95c2": {
                "Name": "tender_murdock",
                "EndpointID": "4bfd68b665c36d61e11af4171b27442f65149cb31ac24bdb7a44b00d4c808c17",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            },
            "f1be3ac60962e647a9a7ca13e44d715f4e93613a0dec77253a4b2bf85db1a855": {
                "Name": "redis-container",
                "EndpointID": "bedeabbf269d728bb9814726adb956892a43dfaca1cbc7579365a6242c255379",
                "MacAddress": "02:42:ac:12:00:03",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
testネットワークに2つのコンテナが含まれていることを確認できます.--networkオプションdocker runで使用すると、コンテナを実行しながらネットワークを直接指定できます.
またdocker-composeを使うことももちろん可能です.
ex) dong@ubuntu:~/docker-complete/DOCKER-NETWORK$ docker run -p 5000:80 -v "$(pwd)"/server.js:/app/server.js --network test network-test-server2つのコンテナが同じネットワークにある場合は、ホストがアクセスする場所にコンテナ名を追加するだけで接続できます.
const express = require('express');
const bodyParser = require('body-parser');
const redis = require('redis');

const app = express();

const client = redis.createClient({
  url: 'redis://redis-container:6379'
});

client.connect();

client.on('connect', () => console.log('Redis Client Connected'));
client.on('error', (err) => console.log('Redis Client Connection Error', err));

let userGoal = 'Enter Your Goal';

app.use(
  bodyParser.urlencoded({
    extended: false,
  })
);

app.use(express.static('public'));

app.get('/', (req, res) => {
  res.send(`
    <html>
      <head>
        <link rel="stylesheet" href="styles.css">
      </head>
      <body>
        <section>
          <h2>My Course Goal</h2>
          <h3>${userGoal}</h3>
        </section>
        <form action="/store-goal" method="POST">
          <div class="form-control">
            <label>Course Goal</label>
            <input type="text" name="goal">
          </div>
          <button>Set Course Goal</button>
        </form>
      </body>
    </html>
  `);
});

app.post('/store-goal', async (req, res) => {
  const enteredGoal = req.body.goal;
  
  await client.set("userGoal", enteredGoal);
  userGoal = await client.get("userGoal");
  res.redirect('/');
});

app.listen(80);
docustomネットワークのデフォルト値はbirdgeですが、host、overlayなど多くの終了方法があります.詳細については、次のリンクを参照してください.
https://docs.docker.com/network/#network-drivers

コンテナとホストの通信


WindowsおよびMacでは、host.docker.internalを使用してホストと通信できます.詳細については、関連ドキュメントを参照してください.
しかしLinuxはhost.docker.ionternalを直接使用することはできません.--add-host=host.docker.internal:host-gatewayオプションを追加してこそ、host.docker.internalでホストと通信できます.--add-host=hostnetwork:host-gatewayに示すように、host.docker.internalではなくhostnetworkを使用して通信してもよい.