The popularity of Docker has prompted many applications to be deployed on it, benefiting from its many advantages. However, compared with traditional non-Docker environments, applications can easily access each other through the 127.0.0.1: port, if Docker containers are not mapped by ports, they cannot directly communicate with each other's ports. Are there better solutions to meet this challenge?
1 Scene Description
Scenario summary: Alpine-client and alpine-server two containers. The former accesses the ports that the latter listens to, in order to explore the port access mechanism between the internal containers of Docker.
2 Create two containers
2.1 Build an image through Dockerfile
Since this test function is very simple, you can create a container through a Dockerfile, and a mirror is loaded into two containers, and the code executed in the container is different.
2.1.1 Create a Dockerfile file
This Dockerfile can be used as a general template and includes a basic functional framework that users can modify on this basis.
# Alpine:3.10-based mirroringFROM alpine:3.10 # Set the mirror source to Tsinghua University mirrorRUN echo "/alpine/v3.10/main" > /etc/apk/repositories \ && echo "/alpine/v3.10/community" >> /etc/apk/repositories \ && apk update && apk upgrade # Install dependency packages and toolsRUN apk add --no-cache \ bash \ netcat-openbsd # Set up the working directoryWORKDIR /root # Copy the required files, support wildcard characters# COPY *.sh /root/ # Add Entrypoint to the Dockerfile and add it as needed# ENTRYPOINT ["/bin/bash", "-c", "/root/"]
A brief explanation of this Dockerfile template file:
1) Quote the basic image
This must have (the statements after this statement are optional), and must be the first sentence. I am used to citing alpine images, which are small and powerful.
2) Set the mirror source
First rewrite the image path file and run update and upgrade to make the changes take effect. Regarding mirror sources, Tsinghua and Alibaba can choose according to your preferences, mainly to speed up the software installation.
3) Install dependency packages and tools
Use the RUN command to perform the installation of dependent packages and tools. The installation work is best performed in one command, so that the image will not add many layers, causing the image file to become larger. Where "\" is used to string together the command strings of branches, and "&&" is used to install multiple commands in sequence.
4) Set up the working directory
After setting up the working directory, the default directory inside the container is the set working directory, which is convenient for operation.
5) Copy the required files
This step allows you to copy the required files from the machine to the image file.
6) Execute the ENTRYPOINT entry script (or use CMD)
When the container starts, the script or command specified here is executed.
2.1.2 Compile the image
docker build -t alpine-net:1.0.0 .
2.2 Generate containers
Generate an alpine-client container:
docker run -itd --name alpine-client alpile-net:1.0.0
Generate an alpine-server container:`
docker run -itd -p 8888:8888 --name alpine-server alpile-net:1.0.0
The alpine-server container has a port map, which maps the 8888 port listened to in alpine-server to the 8888 port of the host of the container.
3 Get the IP address
3.1 Get the alpine-client-related IP address
3.1.1 Get the IP address of the alpine-client container itself
Enter:
ifconfig
After running, the result is as follows:
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:65535 Metric:1
RX packets:197 errors:0 dropped:0 overruns:0 frame:0
TX packets:89 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:22832 (22.2 KiB) TX bytes:5821 (5.6 KiB)lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:7 errors:0 dropped:0 overruns:0 frame:0
TX packets:7 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:524 (524.0 B) TX bytes:524 (524.0 B)
Get two IPs, 127.0.0.1 and 172.17.0.2
3.1.2 Get the alpine-client container gateway IP address
Enter:
route -n
After running, the result is as follows:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
Get the gateway IP address: 172.17.0.1.
3.1.3 Get the alpine-server container gateway IP address
The same operation as above, the process is omitted.
You can get the alpine-server related address:
alpine-server native address: 127.0.0.1 and 172.17.0.3
alpine-server gateway address: 172.17.0.1
4 Test visits
Enter the network port listening command in the alpine-server terminal:
nc -lk 8888 # monitor 8888 port
Listen to port 8888 and test to allow alpine-client to connect. If there is no special description below, the default command line run window is the terminal window with alpine-client
4.1 Access through container name
nc alpine-server 8888
return:
nc: getaddrinfo: Name does not resolve
Tip: The target container name alpine-server cannot be found, so the connection failed!
4.2 Access through container IP
nc 127.17.0.3 8888
Connection failed! This means that the container port is not open to the "next door" container.
4.3 Access through gateway IP
nc 127.17.0.1 8888
Connection failed! This means that container port mapping is not mapped to the gateway.
4.4 Access through docker hostname
docker provides a host name: All containers can access this host name. test:
nc 8888
The connection was successful! And the information entered in alpine-client can be successfully sent to alpine-server, and two-way communication is implemented. This host name allows you to access the port mapped/out of the container, but you cannot access the port inside the container.
4.5 Scheme for creating containers through docker-compose
This part is in my blog postDocker installation and debugging qsign signature server》 has been applied in it, so I will not repeat it here. This method of file has defined the relationship between containers, and incorporates each container into a unified network card. It has a slightly less flexibility and is recommended for mature and stable projects.
The method described in this article adopts "separated type", each container is independent, and the connection between containers is connected by mapping ports, which facilitates dynamic and flexible adjustment of connection relationships and system expansion, etc.
5 Summary
In the scenario where container grouping orchestration has not been implemented, this article explores in depth and reveals an effective way to realize direct mutual access between containers. Compared with the traditional IP address-based access method, the choice as a connection identifier has significant advantages:
1) Stability enhancement:
In the configuration file inside the container, the fixed target address can be hardcoded (i.e. "Write Dead"). This move eliminates configuration vulnerability due to dependence on dynamic allocation or potentially changing IP addresses. The IP address may change when the container is restarted, migrated, or the network environment is adjusted, and using it ensures that the connection pointing is always valid and does not require frequent updates to the configuration as the IP changes.
2) Simplify management:
Adopting as a connection string simplifies the management complexity of interactions between containers. Operations and maintenance personnel do not need to track the specific IP address of each container, nor do they have to manually adjust the configuration files of the associated container when the IP changes. This abstract addressing method makes the dependencies between containers clearer, easier to understand and maintain.
3) Improved compatibility and portability:
It is a special domain name built into the Docker system, aiming to provide a standard, cross-platform way to access services provided by the host. This means that no matter how the actual IP of the host changes, or in different deployment environments (such as development, testing, production), as long as Docker is supported, the domain name can ensure smooth mutual access between containers. This design enhances the compatibility and portability of container applications in different environments.
To sum up, without the intervention of orchestration tools, using mutual access between containers is a both robust and convenient choice. It not only avoids connection failures caused by IP changes, but also simplifies management processes and improves the adaptability of applications in different Docker environments.
This is the article about how to implement port access between docker internal containers. For more related content on port access to docker internal containers, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!