Connecting Containers Together
This lab runs on a real VM
This box is not a Pod but a virtual machine launched by KubeVirt. A separate Linux kernel runs in it, systemd actually manages services, and docker is a real Docker engine, not an imitation. A container started with docker run becomes a real process, and both docker exec and docker logs work as usual.
This lab used to run inside a Pod. That box had dropped every kernel capability, so the step that starts a container was blocked, and you learned by working around it and unpacking image archives by hand. The workaround is no longer needed.
There are two things to know.
- The first start takes a little over a minute. The VM boots and installs Docker, so it is slower than a Pod lab (usually 40 seconds).
- There is no browser preview. Only one grading port is open for connections into the VM. If you start a web server, check it with
curlfrom inside the VM.
Goal
You make containers communicate by name over a user-defined network, confirm that containers on different networks cannot see each other, and build the habit of opening ports only on the loopback.
Why it matters
Most container networking accidents come from two misunderstandings. One is "the container's 127.0.0.1 must be the host's 127.0.0.1", and the other is "I opened the port, so the firewall will protect it". The first is explained by the fact that a network namespace duplicates even the loopback, and the second by the fact that packets going to a container do not have the host as their final destination. The conclusion that restricting the binding address is the simplest and surest control comes from here.
Steps
- Create
/root/ops2and create a user-defined network calleddk-net. - Run
nginx:1.27-alpinein the background with the namedk-api, attached todk-net. - Run
alpine:3.20with the namedk-client, attached to the samedk-net, and keep it running. - From inside
dk-client, send an HTTP request todk-apiby container name and save the response to/root/ops2/dns.txt. It is enough if the default nginx page is in it. - Create a new network called
dk-net2and start adk-lonelycontainer attached only to that network. Confirm thatdk-lonelycannot reachdk-api, and in/root/ops2/isolated.txtwriteunreachable. - Start
nginx:1.27-alpinewith the namedk-pub, publishing the container's port 80 only on port 8080 of127.0.0.1. - Do not delete
dk-lonely; connect it additionally todk-netas well, then check whether the namedk-apinow resolves. - In
/root/ops2/net.md, write one line each fordk-api,dk-client,dk-lonelyanddk-pub, and in thedk-lonelyline also put the number of networks it belongs to, and in thedk-publine the published binding address and port.
Notes
- Add a network to an already running container with
docker network connect <네트워크> <컨테이너>(put the network name and the container name in place of the placeholders). - You can check name resolution alone with
docker exec dk-client getent hosts dk-api. - This environment is rootless, so you cannot open ports below 1024. Use 8080.
- Common mistake 1: if you simply start alpine in step 3, it ends immediately. Give it a command that keeps running.
- Common mistake 2: if you omit the binding address in step 6, it opens on all interfaces. Grading counts this as a failure.
Create a user-defined network
Create /root/ops2 and create a user-defined network called dk-net.
There is a group of subcommands for handling networks. The reason not to use the default bridge is name resolution.
Attach a container to the network
Run nginx:1.27-alpine in the background with the name dk-api, attached to dk-net.
When you start a container, you can specify which network to attach it to. Check with NetworkSettings.Networks in inspect.
One more on the same network
Run alpine:3.20 with the name dk-client, attached to the same dk-net, and keep it running.
The second container must keep running so that you can run commands inside it.
Find each other by name
From inside dk-client, send an HTTP request to dk-api by container name and save the response to /root/ops2/dns.txt. It is enough if the default nginx page is in it.
On the same user-defined network, the container name is the hostname. Send an HTTP request from inside and save the response.
Another network is not visible
Create a new network called dk-net2 and start a dk-lonely container attached only to that network. Confirm that dk-lonely cannot reach dk-api, and in /root/ops2/isolated.txt write unreachable.
Try to access it from a container attached only to the new network and record the result as a conclusion word.
Open a port to the host
Start nginx:1.27-alpine with the name dk-pub, publishing the container's port 80 only on port 8080 of 127.0.0.1.
If you omit the binding address, it opens on all interfaces. Restrict it to the loopback. Ports below 1024 cannot be opened in this environment.
Attach an already running container to a network as well
Do not delete dk-lonely; connect it additionally to dk-net as well, then check whether the name dk-api now resolves.
There is a command that attaches a network without recreating the container. The existing connection must be kept.
Summarize the reachability
In /root/ops2/net.md, write one line each for dk-api, dk-client, dk-lonely and dk-pub, and in the dk-lonely line also put the number of networks it belongs to, and in the dk-pub line the published binding address and port.
Write with the actual values which networks each container is attached to and how many, and which ports are open where.