WSL-Docker Port Forwarding Manager CLI
This PowerShell script is a simple CLI tool designed to manage port forwarding rules on a Windows machine. It allows users to list, add, and remove port forwarding rules for connections between a Windows host and WSL (Windows Subsystem for Linux).
Features
- List Existing Rules: Display currently active port forwarding rules.
- Add New Rule: Add a new port forwarding rule between a Windows IP/port and a WSL IP/port.
- Remove Rule: Remove a port forwarding rule by specifying the Windows IP and port.
Requirements
- PowerShell (Windows or PowerShell 7+ recommended).
- Administrator privileges (required for managing port forwarding rules).
Usage
1. Listing Existing Port Forwarding Rules
To list the current port forwarding rules:
- Select option 1 from the menu.
- This will run
netsh interface portproxy show allto display the active rules.
2. Adding a New Port Forwarding Rule
To add a new port forwarding rule:
- Select option 2 from the menu.
- Enter the following details when prompted:
- Windows Host IP: The IP address of the Windows machine (e.g.,
192.168.1.100). - Windows Host Port: The port on the Windows machine you wish to forward (e.g.,
8080). - WSL IP: The IP address of your WSL instance (e.g.,
172.18.8.1). - WSL Port: The port on your WSL instance to forward to (e.g.,
80).
- Windows Host IP: The IP address of the Windows machine (e.g.,
- The script will then add the rule using the
netshcommand.
3. Removing a Port Forwarding Rule
To remove a port forwarding rule:
- Select option 3 from the menu.
- Enter the Windows Host IP and Windows Host Port associated with the rule you wish to remove.
- The script will delete the rule using the
netshcommand.
4. Exiting the Script
To exit the script:
- Simply press Ctrl + C at any time or select option 4 to exit (if added).
Example Workflow
Port Forwarding Manager CLI
1. List Existing Rules
2. Add New Rule
3. Remove Rule
Enter your choice (1-3) or Ctrl + C to exit: 1
Listing existing port forwarding rules...
Protocol LocalAddress LocalPort ForeignAddress ForeignPort
-------- -------------------- --------- -------------------- ----------
TCP 192.168.1.100 8080 172.18.8.1 80
TCP 192.168.1.100 443 172.18.8.1 443
Installation and Setup
1. Download Script
You can either download or copy the contents of the script into a .ps1 file (e.g., PortForwardingManager.ps1) manually.
Or you can use git clone https://github.com/FluffyClaws/win-docker-port-forwarding
2. Run Script with Administrator Privileges
The script needs to be run with administrator privileges to manage port forwarding rules. To run the script:
-
Open PowerShell as an administrator.
-
Navigate to the folder where the script is saved.
-
Run the script using the following command:
powershell
Copy code
.\PortForwardingManager.ps1
Alternatively, you can configure your script to be launched with administrator rights by creating a shortcut or using a command line (see the instructions in previous responses for running with admin privileges).
Error Handling
- If you attempt to add or remove a rule with missing or incorrect information (e.g., IP address or port), the script will prompt you to enter all required fields.
- The script will notify you if a rule is successfully added or removed.
Troubleshooting
- If the script doesn’t run, ensure you are running it as an administrator.
- If port forwarding is not working as expected, check that the WSL instance is correctly configured and accessible on the specified IP.
When you work with Docker, you sometimes need to use docker-machine. Docker-machine is a tool that helps you create and manage Docker hosts. Many times, these hosts run in a virtual machine. In such cases, you may not be able to reach your containers easily from your main computer. This is where port forwarding comes in. In this article, we will learn how to set up port forwarding in docker-machine. I try to use simple words and short sentences so it is easy to follow.
Introduction
Docker-machine makes it simple to run Docker on many environments. It creates a virtual machine on your computer or in the cloud. However, when you use a virtual machine, the ports used by your containers are not automatically open on your host computer. To access your containers from your host, you need to forward ports from the virtual machine to your computer. This process is called port forwarding.
Port forwarding helps you send traffic from a port on your host machine to a port on the virtual machine. This allows you to test your applications in a container and access them as if they were running on your computer. For more details on how container ports work, you can read about understanding Docker container ports.
What is docker-machine?
Docker-machine is a tool that creates and manages Docker hosts. It is useful when you want to run Docker on a local virtual machine or on cloud platforms. When you run docker-machine, it creates a virtual machine using a driver like VirtualBox. Once the machine is ready, you can use it to run your Docker containers.
Because docker-machine creates a separate virtual machine, the IP address of this machine is different from your computer’s IP address. To access services running inside the machine, you must know its IP address. You can get this by running:
docker-machine ip default
Enter fullscreen mode
Exit fullscreen mode
Here, «default» is the name of your docker-machine. This command shows the IP address of your Docker host.
If you want to learn more about Docker and why you should use it, check out what is Docker and why you should use it.
What is Port Forwarding?
Port forwarding is a method to redirect network traffic. In our case, it means sending traffic from a port on your host machine to a port on the virtual machine created by docker-machine. By doing this, you can access the container’s application from your host computer. For example, if a web server runs on port 8080 inside the container, you can forward this port so that it is available on your host machine as well.
This idea is very similar to exposing ports in Docker containers. However, with docker-machine, an extra step is needed because of the virtual machine layer. You have to set up rules to forward the traffic correctly.
How Port Forwarding Works in docker-machine
When docker-machine creates a virtual machine, it usually sets up a Network Address Translation (NAT) connection. NAT hides the virtual machine behind a private network. With NAT, the ports used by containers are not automatically accessible from the host computer.
To allow communication, you must create port forwarding rules. These rules tell the virtual machine to listen on a specific port on its host interface and then pass the traffic to a specific port on the container. For example, you may want to forward port 8080 on your computer to port 8080 in a container running inside the virtual machine.
A good explanation on exposing container ports to the host can help you understand why this step is necessary. It shows that without port forwarding, the service in the container remains hidden.
Setting Up Port Forwarding in VirtualBox
Most docker-machine users use VirtualBox as the virtual machine driver. In VirtualBox, you can set up port forwarding using the VirtualBox command-line tool called VBoxManage or by using the VirtualBox graphical user interface (GUI).
Using VBoxManage
If you are comfortable with the command line, you can use VBoxManage. First, find the name of your docker-machine. It is often «default» unless you have changed it. Then run a command like this:
VBoxManage modifyvm "default" --natpf1 "tcp-port8080,tcp,,8080,,8080"
Enter fullscreen mode
Exit fullscreen mode
Let’s break down the command:
- VBoxManage modifyvm «default» tells VirtualBox to modify the settings of the virtual machine named «default».
-
—natpf1 «tcp-port8080,tcp,,8080,,8080» sets a NAT port forwarding rule.
- The rule is named «tcp-port8080».
- The first «tcp» indicates the protocol.
- The first empty field means the host IP is not specified (it listens on all interfaces).
- The second «8080» is the port on the host.
- The next empty field means the guest IP is not specified.
- The final «8080» is the port on the virtual machine.
This command forwards traffic from port 8080 on your host computer to port 8080 on the docker-machine virtual machine.
Using VirtualBox GUI
If you prefer a graphical interface:
- Open VirtualBox.
- Select your docker-machine virtual machine (often named «default»).
- Go to Settings > Network.
- Click on Advanced and then Port Forwarding.
- Add a new rule with the following details:
- Name: tcp-port8080
- Protocol: TCP
- Host IP: Leave empty or 127.0.0.1
- Host Port: 8080
- Guest IP: Leave empty
- Guest Port: 8080
This does the same as the VBoxManage command and forwards port 8080.
For more details on exposing ports, you may also refer to exposing ports in Docker containers.
Running a Container with Port Forwarding
After setting up port forwarding on your virtual machine, you can run a container in docker-machine as usual. For example, if you want to run a web server on port 8080, you can use:
docker run -d -p 8080:80 --name my_webserver nginx
Enter fullscreen mode
Exit fullscreen mode
This command does the following:
- -d runs the container in detached mode.
- -p 8080:80 maps port 8080 on the virtual machine to port 80 inside the container.
- —name my_webserver gives the container a name.
- nginx is the image used (running a web server).
Now, with port forwarding set up in VirtualBox, you can access the web server from your host computer by going to http://localhost:8080. The request goes to your host computer, then is forwarded by VirtualBox to the docker-machine virtual machine, and finally reaches the container on port 80.
A helpful article on exposing container ports to the host explains this mapping in more detail.
Troubleshooting Port Forwarding Issues
Even when you follow the steps, you might face some problems. Here are a few common issues and their fixes:
1. Incorrect Port Numbers
Make sure you use the same port numbers in your port forwarding rule and in your docker run command. If you forward host port 8080, then your container should be mapped accordingly.
2. Virtual Machine Not Running
Before accessing your service, ensure that your docker-machine is running. Use the command:
docker-machine ls
Enter fullscreen mode
Exit fullscreen mode
This shows the status of your machines. If your machine is not running, start it with:
docker-machine start default
Enter fullscreen mode
Exit fullscreen mode
3. Firewall Settings
Your host computer’s firewall may block the forwarded port. Ensure that port 8080 is allowed. You may need to adjust your firewall settings.
4. Conflicting Applications
If another application is using port 8080 on your host, you may need to change the host port in your forwarding rule. For example, you can set the rule to forward port 9090 instead:
VBoxManage modifyvm "default" --natpf1 "tcp-port9090,tcp,,9090,,8080"
Enter fullscreen mode
Exit fullscreen mode
And run the container with:
docker run -d -p 8080:80 --name my_webserver nginx
Enter fullscreen mode
Exit fullscreen mode
Now, access the service at http://localhost:9090.
Best Practices for Port Forwarding in docker-machine
Here are some tips to make port forwarding work smoothly in docker-machine:
-
Use Consistent Port Numbers:
Always use the same port numbers in your Docker run commands and in your VirtualBox settings. This helps avoid confusion.
-
Document Your Settings:
Write down the port forwarding rules you create. It will help you remember which ports are forwarded if you need to update your configuration later.
-
Check Docker-Machine Status Regularly:
Use
docker-machine lsto ensure your virtual machine is running properly. -
Test Access Often:
After setting up port forwarding, test your application by accessing the forwarded port in your web browser. This confirms that the rules are correct.
For more advanced setups, you can also look at using Docker with cloud environments. This article explains how Docker can work with cloud providers and may give you ideas if you want to move beyond a local VirtualBox setup.
Example Scenario
Let’s walk through a real-world example. Imagine you are developing a web application that runs inside a Docker container. You use docker-machine with VirtualBox on your laptop. You want to see your application in a web browser on your host computer.
Step 1: Create and Start Docker-Machine
If you do not already have a docker-machine, create one using:
docker-machine create --driver virtualbox default
Enter fullscreen mode
Exit fullscreen mode
Then, start it:
docker-machine start default
Enter fullscreen mode
Exit fullscreen mode
Step 2: Set Up Port Forwarding
Using VirtualBox’s command line, run:
VBoxManage modifyvm "default" --natpf1 "tcp-web,tcp,,8080,,8080"
Enter fullscreen mode
Exit fullscreen mode
This rule forwards traffic from port 8080 on your host to port 8080 on the docker-machine.
Step 3: Run Your Web Application Container
Run your container with port mapping:
docker run -d -p 8080:80 --name my_web_app nginx
Enter fullscreen mode
Exit fullscreen mode
This command maps port 8080 on the docker-machine (forwarded from your host) to port 80 in the container.
Step 4: Access Your Application
Open your web browser and go to:
http://localhost:8080
Enter fullscreen mode
Exit fullscreen mode
Your request goes to your host computer, is forwarded to the docker-machine virtual machine, and finally reaches the container running the Nginx web server. You should see the default Nginx welcome page.
This scenario shows how port forwarding makes it possible to work with docker-machine easily. For a deeper understanding of how container ports are set up, check out the guide on exposing container ports to the host.
Additional Considerations
When you set up port forwarding in docker-machine, keep the following in mind:
-
Driver Differences:
While VirtualBox is common, other drivers may have different ways of handling port forwarding. Always check the documentation for your chosen driver.
-
Multiple Forwarding Rules:
You can forward more than one port. Repeat the process with different port numbers for each service you want to access.
-
Use of Docker CLI:
Working with docker-machine and port forwarding can be managed via the Docker CLI. Learning more about how to work with containers using the Docker CLI can be helpful. For more on this topic, you might want to review articles on working with Docker containers using the Docker CLI.
-
Security Considerations:
Be careful when exposing ports to the public. Ensure that only the necessary ports are forwarded and that your firewall settings are correctly configured.
-
Testing Your Configuration:
After making changes, always test your configuration by accessing your application. Simple tools like
curlcan help you check connectivity from the command line.
Conclusion
Port forwarding in docker-machine is an important skill for anyone using Docker with virtual machines. By setting up port forwarding, you can access your containerized applications easily from your host computer. We learned that docker-machine creates a virtual machine where Docker runs. Because the virtual machine has its own IP address, you must forward ports so that services inside containers are reachable.
We also learned how to set up port forwarding using VirtualBox. You can use the VBoxManage command line tool or the VirtualBox GUI to create rules that forward traffic from your host machine to the docker-machine. In our example, we forwarded port 8080 and ran an Nginx container to demonstrate how it works.
Remember to use consistent port numbers and test your setup often. Good documentation and regular checks with commands like docker-machine ls will help you maintain a reliable environment. For further reading on container networking, consider exploring the topic of exposing ports in Docker containers.
If you want to know more about Docker and its features, you might also be interested in reading about what is Docker and why you should use it. And for those who work with cloud services, the guide on using Docker with cloud environments can provide additional insights.
I hope this guide helps you understand how to do port forwarding in docker-machine. Keep practicing and testing your configuration. With time, these steps will become simple and natural in your workflow. Happy containerizing and good luck with your projects!
Docker port forwarding or port mapping redirects a communication request from one IP address and port number combination to another. Port forwarding exposes services to applications outside the host’s internal network.
Here, port forwarding allows remote client applications to connect to the NCache servers running inside Docker containers (internal Docker network).
Docker Port Forwarding Configuration
There are some scenarios where you cannot access the NCache servers running inside Docker containers directly. You’ll have to map NCache ports from the containers to the host machine network for accessibility. Additionally, you’ll have to configure these ports for the client application. The configuration for both is explained below:
Configure Port Forwarding in Containers
Before you proceed with docker port forwarding, you need to assign NCache containers static IP addresses. NCache servers need to have static IP addresses to communicate with each other and with NCache clients. Also, NCache servers are not accessible to the NCache clients if both don’t exist on the same network or subnet.
Step 1: Create a Custom Docker Network
By default, Docker assigns containers dynamic IP addresses. Therefore, if the containers have to restart or the host machine restarts, the IP addresses of the containers might change. To assign containers static IP addresses, a custom Docker network is required.
The following command creates a custom Docker network named nbrg with a subnet and gateway defined:
docker network create --subnet=172.19.0.0/16 --gateway=172.19.0.1 nbrg
Step 2: Create NCache Containers and Map NCache Ports
Once the custom Docker network creation occurs, you may assign NCache containers static IP addresses and map NCache ports from the containers to the host for accessibility.
The following commands create two NCache Docker containers named ncache-ent-server-01 and ncache-ent-server-02. Two containers are assigned static IP addresses using the custom Docker network nbrg creat in the last step. The NCache communication ports map from the containers to the host using the Docker -p switch:
docker run --name ncache-ent-server-01 --net nbrg --ip 172.19.0.11 -p 1250-1260:8250-8260 -p 1300-1400:8300-8400 -p 9801:9800 -itd alachisoft/ncache:latest-java
docker run --name ncache-ent-server-02 --net nbrg --ip 172.19.0.12 -p 2250-2260:8250-8260 -p 2300-2400:8300-8400 -p 9802:9800 -itd alachisoft/ncache:latest-java
Configure Docker Port Forwarding for Client Application
Once you have mapped the ports from the containers to the host, you need to reflect that change for the client application, as well. The client.ncconf file uses the client application to establish a connection with the NCache servers. You need to map the ports and the IP addresses in this file.
The following is a client.ncconf file configuration where the ports map with the containers (NCache servers) ncache-ent-server-01 and ncache-ent-server-02, which were created previously and are hosted on the public IP address 20.200.20.212:
<configuration>
<ncache-server connection-retries="1" retry-connection-delay="0" retry-interval="1" command-retries="3" command-retry-interval="0.1" client-request-timeout="90" connection-timeout="5" port="9800"/>
<cache id="demoCache" client-cache-id="" client-cache-syncmode="optimistic" skip-client-cache-if-unavailable="True" reconnect-client-cache-interval="10" default-readthru-provider="" default-writethru-provider="" load-balance="True" enable-client-logs="False" log-level="error">
<server name="172.19.0.11"/>
<server name="172.19.0.12"/>
</cache>
<server-end-point>
<end-point public-ip="20.200.20.212" public-ports="9801" private-ip="172.19.0.11" private-ports="9800"/>
<end-point public-ip="20.200.20.212" public-ports="1250-1260" private-ip="172.19.0.11" private-ports="8250-8260"/>
<end-point public-ip="20.200.20.212" public-ports="1300-1400" private-ip="172.19.0.11" private-ports="8300-8400"/>
<end-point public-ip="20.200.20.212" public-ports="9802" private-ip="172.19.0.12" private-ports="9800"/>
<end-point public-ip="20.200.20.212" public-ports="2250-2260" private-ip="172.19.0.12" private-ports="8250-8260"/>
<end-point public-ip="20.200.20.212" public-ports="2300-2400" private-ip="172.19.0.12" private-ports="8300-8400"/>
</server-end-point>
</configuration>
See Also
NCache Docker Deployment Scenarios
NCache Docker on Windows
NCache Docker on Linux
Время на прочтение7 мин
Количество просмотров15K
Современные приложения активно используют сети. Обычное дело, когда во время сборки apt-get/dnf/yum/apk install устанавливает пакет из репозитория пакетов дистрибутива Linux. При выполнении команды приложение может захотеть подключиться к внутренней базе данных postgres или mysql, чтобы сохранить определённое состояние при вызове listen() и accept(). При этом разработчик должен иметь возможность работать отовсюду — из дома или офиса, с мобильного устройства или через VPN. Docker Desktop помогает сделать так, чтобы сеть «просто работала» в каждом из сценариев. В статье разбираем инструменты и методы, которые обеспечивают это, начиная с всеми любимого набора протоколов: TCP/IP.
TCP/IP
TCP/IP — набор протоколов, который задаёт стандарты связи между компьютерами и содержит подробные соглашения о маршрутизации и межсетевом взаимодействии. Когда контейнер хочет подключиться к внешнему миру, он используют TCP/IP. Поскольку для Linux-контейнеров требуется ядро Linux, Docker Desktop включает вспомогательную виртуальную машину Linux. В результате трафик из контейнеров идёт от виртуальной машины Linux, а не от хоста, что вызывает серьёзную проблему.
Многие IT-отделы создают политики VPN, где говорится что-то вроде «перенаправлять через VPN только трафик, исходящий от хоста». Смысл в том, чтобы предотвратить случайное действие хоста в качестве маршрутизатора, перенаправляющего небезопасный трафик из интернета в защищенные корпоративные сети. Если программа VPN увидит трафик с виртуальной машины Linux, он не будет маршрутизироваться через VPN, что не позволит контейнерам получить доступ к внутренним ресурсам.
Docker Desktop помогает избежать этой проблемы, перенаправляя весь трафик на уровне пользователя через vpnkit и стек TCP/IP, написанный на OCaml поверх библиотек сетевых протоколов проекта MirageOS. На диаграмме показан поток пакетов от вспомогательной виртуальной машины через vpnkit и в Интернет:
При загрузке виртуальная машина запрашивает адрес с помощью DHCP. Ethernet-фрейм, содержащий запрос, передаётся от виртуальной машины к хосту через общую память, либо через virtio на Mac, либо через AF_VSOCK на Windows. Vpnkit содержит виртуальный коммутатор ethernet (mirage-vnetif), который перенаправляет запрос на сервер DHCP (mirage/charrua).
Как только виртуальная машина получает ответ DHCP, содержащий IP-адрес виртуальной машины и IP-адрес шлюза, она отправляет запрос ARP для определения адреса сетевого шлюза (mirage/arp). После получения ответа ARP он сможет отправить пакет в Интернет.
Когда vpnkit видит исходящий пакет с новым IP-адресом, он создаёт виртуальный стек TCP/IP для удалённой машины (mirage/mirage-tcpip). Этот стек действует как одноранговый стек в Linux — принимает и обменивается пакетами. Когда контейнер вызывает connect() для установления TCP-соединения, Linux отправляет TCP-пакет с установленным флагом SYNchronize. Vpnkit наблюдает за флагом SYNchronize и сам вызывает connect() с хоста. Если connect() завершается успешно, vpnkit отвечает Linux пакетом TCP SYNchronize. В Linux connect() выполняется успешно, и данные проксируются в обоих направлениях (mirage/mirage-flow). Если connect() отклоняется, vpnkit отвечает пакетом TCP RST (reset), который заставляет connect() внутри Linux возвращать ошибку. UDP и ICMP обрабатываются аналогичным образом.
Помимо низкоуровневого TCP/IP, vpnkit имеет ряд встроенных высокоуровневых сетевых служб, например, DNS-сервер (mirage/ocaml-dns) и HTTP-прокси (mirage/cohttp). К этим службам можно обращаться напрямую — через виртуальный IP-адрес или DNS-имя, и косвенно — путем сопоставления исходящего трафика и динамического перенаправления в зависимости от конфигурации.
«Docker для админов и разработчиков»
С адресами TCP/IP трудно работать напрямую. В следующем разделе разберём, как Docker Desktop использует DNS для присвоения удобочитаемых имён сетевым службам.
DNS
Внутри Docker Desktop есть несколько DNS-серверов:
DNS-запросы от контейнеров сначала обрабатываются сервером внутри dockerd, который распознаёт имена других контейнеров в той же внутренней сети. Это позволяет контейнерам легко взаимодействовать друг с другом даже без знания внутренних IP-адресов. Каждый раз, когда приложение запускается, внутренние IP-адреса могут быть разными, но контейнеры по-прежнему будут легко подключаться друг к другу по удобочитаемому имени благодаря внутреннему DNS-серверу внутри dockerd.
Остальные поисковые запросы отправляются в CoreDNS (из CNCF). Затем в зависимости от доменного имени запросы перенаправляются на один из двух DNS-серверов на хосте. Домен docker.internal считается особенным и включает в себя DNS-имя host.docker.internal, которое преобразуется в IP-адрес для текущего хоста. Хотя предпочтительнее, когда всё контейнеризировано, иногда имеет смысл запускать часть приложения как обычный сервис хостинга. Имя host.docker.internal позволяет контейнерам связываться с этими хост-сервисами и не беспокоиться о хардкодинге IP-адресов.
Второй DNS-сервер на хосте обрабатывает остальные запросы с помощью стандартных системных библиотек ОС. Это гарантирует, что, если имя правильно разрешится в веб-браузере разработчика, оно также будет правильно разрешаться в контейнерах. Это особенно важно при сложных настройках, например, когда одни запросы отправляются через корпоративный VPN (internal.registry.mycompany), в то время как другие — через обычный интернет (docker.com).
HTTP(S)-прокси
Некоторые организации блокируют прямой доступ в интернет и требуют, чтобы весь трафик направлялся через HTTP-прокси для фильтрации и логирования. Это влияет на извлечение образов во время сборки, а также на исходящий сетевой трафик, генерируемый контейнерами.
Самый простой способ использования HTTP-прокси — указать движку Docker на прокси-сервер c помощью переменных среды. Единственный недостаток: при необходимости изменения прокси-сервера придётся перезапустить Docker для обновления переменных, что приведёт к сбою. Docker Desktop позволяет избежать этого. Он запускает собственный HTTP-прокси внутри vpnkit, который перенаправляет на восходящий прокси-сервер. При изменении восходящего прокси-сервера внутренний прокси-сервер динамически перенастраивается, что позволяет избежать перезапуска.
На Mac Docker Desktop отслеживает параметры прокси-сервера, сохраненные в системных настройках. Когда компьютер переключает сеть (например, между сетями Wi-Fi или на сотовую связь), Docker Desktop автоматически обновляет внутренний HTTP-прокси, поэтому всё продолжает работать без каких-либо действий со стороны разработчика.
Port forwarding
Порты позволяют сетевым и подключенным к интернету устройствам взаимодействовать через указанные каналы. Хотя серверы с назначенными IP-адресами могут подключаться к интернету напрямую и делать порты публично доступными, система, находящаяся за пределами локальной сети, может оказаться недоступной из интернета. Port Forwarding — технология проброса портов, которая позволяет преодолеть это ограничение и сделать устройства публично доступными. Доступ предоставляется с помощью перенаправления трафика определённых портов с внешнего адреса маршрутизатора на адрес выбранного компьютера в локальной сети.
Поскольку Docker Desktop запускает Linux-контейнеры внутри виртуальной машины Linux, возникает разрыв: порты на виртуальной машине открыты, но инструменты работают на хосте. Нам нужно что-то для перенаправления соединений с хоста на виртуальную машину.
Рассмотрим отладку веб-приложения: разработчик вводит docker run -p 80:80, чтобы порт 80 контейнера был открыт на порту 80 хоста (и чтобы сделать его доступным через http://localhost). Вызов Docker API записывается в /var/run/docker.sock на хосте, как обычно. Когда Docker Desktop запускает Linux-контейнеры, движок Docker представляет собой программу Linux, работающую внутри вспомогательной виртуальной машины Linux, а не на хосте. Поэтому Docker Desktop включает в себя прокси-сервер Docker API, который пересылает запросы с хоста на виртуальную машину. В целях безопасности запросы не пересылаются напрямую по протоколу TCP по сети. Вместо этого Docker Desktop перенаправляет соединения с доменными сокетами Unix по защищенному низкоуровневому пути через процессы, обозначенные на схеме выше как vpnkit-bridge.
Прокси Docker API может делать больше, чем просто пересылать запросы туда и обратно. Он также может декодировать и преобразовывать запросы и ответы, чтобы улучшить работу разработчика. Когда разработчик предоставляет порт с помощью docker run -p 80:80, прокси Docker API декодирует запрос и использует внутренний API для переадресации порта через процесс com.docker.backend. Если что-то на хосте уже прослушивает этот порт, разработчику возвращается удобочитаемое сообщение об ошибке. Если порт свободен, процесс com.docker.backend начинает принимать соединения и перенаправлять их в контейнер через vpnkit-forwarder, запущенный поверх vpnkit-bridge.
Docker Desktop не запускается с «root» или «Administrator» на хосте. Разработчик может использовать docker run –privileged , чтобы получить права root внутри вспомогательной виртуальной машины, но гипервизор гарантирует, что хост всегда будет защищён. Это хорошо с точки зрения безопасности, но вызывает проблему удобства использования в macOS — как разработчик может открыть порт 80 (docker run -p 80:80), когда он считается «привилегированным портом» в Unix, то есть номер порта < 1024? Решение состоит в том, что Docker Desktop включает в себя вспомогательную привилегированную службу, которая запускается от имени root из launchd и которая говорит API «пожалуйста, привяжите этот порт». В связи с этим возникает вопрос: безопасно ли разрешать пользователю без полномочий root привязывать привилегированные порты?
Привилегированные порты изначально были функцией безопасности. Они появились во времена, когда порты использовались для аутентификации сервисов: можно было с уверенностью предположить, что вы разговариваете с HTTP-демоном хоста, потому что он привязан к порту 80, для которого требуется root. Современный способ аутентификации — с помощью сертификатов TLS и отпечатков пальцев SSH. Поэтому пока системные службы связывают свои порты до запуска Docker Desktop, macOS связывает порты при загрузке через launchd, благодаря чему не может быть путаницы или отказа в обслуживании. Соответственно, современная macOS сделала привязку привилегированных портов ко всем IP-адресам (0.0.0.0 или INADDR_ANY) непривилегированной операцией. Есть только один случай, когда Docker Desktop все ещё нуждается в использовании привилегированного помощника для привязки портов: когда запрашивается определенный IP (например, docker run -p 127.0.0.1:80:80), для которого требуется root в macOS.
Коротко о главном
Извлечение образов Docker, установка пакетов Linux, взаимодействие с серверными частями базы данных — всё это ежедневные задачи, для выполнения которых приложениям нужны надёжные сетевые подключения. Docker Desktop работает в самых разных средах: в офисе, дома и даже в поездках с нестабильным Wi-Fi. Однако на каких-то компьютерах могут быть установлены ограничительные политики брандмауэра, на каких-то — сложные конфигурации VPN. В таких случаях Docker Desktop стремится «просто работать», чтобы разработчик мог сосредоточиться на создании и тестировании своего приложения (а не на отладке Docker).
«Docker для админов и разработчиков»
Contents
- Introduction
- Introduction to Docker Containers
- Understanding Port Mapping in Docker
- Exposing Ports for Application Access
- Mapping Ports Between Containers and Host
- Configuring Port Forwarding in Docker Compose
- Best Practices for Port Forwarding
- Summary
Introduction
This tutorial will guide you through the process of forwarding ports in Docker containers to provide external access to your applications. You will learn how to expose ports, map them between containers and the host, and configure port forwarding in Docker Compose. By the end of this article, you will have a solid understanding of Docker port forwarding and be able to apply it to your own projects.
Skills Graph
%%%%{init: {‘theme’:’neutral’}}%%%%
flowchart RL
docker((«Docker»)) -.-> docker/ContainerOperationsGroup([«Container Operations»])
docker((«Docker»)) -.-> docker/NetworkOperationsGroup([«Network Operations»])
docker((«Docker»)) -.-> docker/DockerfileGroup([«Dockerfile»])
docker/ContainerOperationsGroup -.-> docker/run(«Run a Container»)
docker/ContainerOperationsGroup -.-> docker/start(«Start Container»)
docker/ContainerOperationsGroup -.-> docker/stop(«Stop Container»)
docker/ContainerOperationsGroup -.-> docker/create(«Create Container»)
docker/ContainerOperationsGroup -.-> docker/port(«List Container Ports»)
docker/NetworkOperationsGroup -.-> docker/network(«Manage Networks»)
docker/DockerfileGroup -.-> docker/build(«Build Image from Dockerfile»)
subgraph Lab Skills
docker/run -.-> lab-393010{{«Forwarding Ports in Docker Containers for Application Access»}}
docker/start -.-> lab-393010{{«Forwarding Ports in Docker Containers for Application Access»}}
docker/stop -.-> lab-393010{{«Forwarding Ports in Docker Containers for Application Access»}}
docker/create -.-> lab-393010{{«Forwarding Ports in Docker Containers for Application Access»}}
docker/port -.-> lab-393010{{«Forwarding Ports in Docker Containers for Application Access»}}
docker/network -.-> lab-393010{{«Forwarding Ports in Docker Containers for Application Access»}}
docker/build -.-> lab-393010{{«Forwarding Ports in Docker Containers for Application Access»}}
end
Introduction to Docker Containers
Docker is a popular open-source platform that enables developers to build, deploy, and run applications in a containerized environment. Containers are lightweight, standalone, and executable software packages that include everything needed to run an application, including the code, runtime, system tools, and libraries.
Docker containers provide a consistent and reliable way to package and distribute applications, ensuring that they will run the same way regardless of the underlying infrastructure. This makes it easier to develop, test, and deploy applications, as well as to scale and manage them in production.
To get started with Docker, you’ll need to install the Docker engine on your system. On Ubuntu 22.04, you can do this by running the following commands:
sudo apt-get update
sudo apt-get install -y docker.io
sudo systemctl start docker
sudo systemctl enable docker
Once you have Docker installed, you can create and manage containers using the docker command-line tool. For example, to create a new container based on the official Ubuntu image, you can run:
docker run -it ubuntu:latest /bin/bash
This will start a new container based on the latest Ubuntu image and drop you into a bash shell inside the container. From here, you can install additional software, run your application, and more.
Overall, Docker containers provide a powerful and flexible way to develop, deploy, and manage applications, making it easier to ensure consistent and reliable application behavior across different environments.
Understanding Port Mapping in Docker
Ports and Networking in Docker Containers
When you run a container, it is isolated from the host system and other containers, including its own network stack. This means that any network ports exposed by the application running inside the container are only accessible within the container itself.
To make the application accessible from outside the container, you need to map the container’s ports to corresponding ports on the host system. This process is known as «port mapping» or «port forwarding».
Exposing Ports in Docker
To expose a port in a Docker container, you can use the -p or --publish flag when running the docker run command. For example, to expose port 80 in the container and map it to port 8080 on the host, you can run:
docker run -p 8080:80 nginx
This will start an Nginx web server container and map port 80 inside the container to port 8080 on the host system.
You can also specify multiple port mappings by using the -p flag multiple times:
docker run -p 8080:80 -p 8443:443 nginx
This will map port 80 in the container to port 8080 on the host, and port 443 in the container to port 8443 on the host.
Accessing Mapped Ports
Once you have mapped a port in the container to a port on the host, you can access the application running in the container by connecting to the corresponding port on the host. For example, if you have mapped port 8080 on the host to port 80 in the container, you can access the application by visiting http://localhost:8080 in your web browser.
Overall, understanding port mapping is crucial for making your Docker-based applications accessible from outside the container, and for enabling communication between containers and other systems.
Exposing Ports for Application Access
Identifying Application Ports
The first step in exposing ports for application access is to identify the ports that your application is listening on. This information is typically provided in the application’s documentation or can be determined by inspecting the application’s code or configuration.
For example, if you are running a web server like Nginx, it is likely listening on port 80 (HTTP) and/or port 443 (HTTPS). If you are running a database server, it might be listening on a specific port like 3306 for MySQL or 5432 for PostgreSQL.
Exposing Ports with the docker run Command
Once you have identified the ports that your application is using, you can expose them to the host system using the -p or --publish flag when running the docker run command. This will map the container’s ports to corresponding ports on the host system.
For example, to expose port 80 in the container and map it to port 8080 on the host, you can run:
docker run -p 8080:80 nginx
This will start an Nginx web server container and map port 80 inside the container to port 8080 on the host system.
Exposing Multiple Ports
You can expose multiple ports by using the -p flag multiple times. For example, to expose port 80 and 443 in the container and map them to ports 8080 and 8443 on the host, you can run:
docker run -p 8080:80 -p 8443:443 nginx
This will map port 80 in the container to port 8080 on the host, and port 443 in the container to port 8443 on the host.
By exposing the appropriate ports, you can ensure that your Docker-based applications are accessible from outside the container, allowing users and other systems to interact with your applications.
Mapping Ports Between Containers and Host
Understanding Port Mapping Syntax
When exposing ports in Docker, you use the following syntax to map a container port to a host port:
-p <host_port>:<container_port>
For example, to map port 8080 on the host to port 80 in the container, you would use:
docker run -p 8080:80 nginx
This maps port 80 in the container to port 8080 on the host system.
Mapping Ports Dynamically
Instead of specifying a specific host port, you can also let Docker choose an available port on the host system by omitting the host port:
docker run -p 80 nginx
This will map an available port on the host system to port 80 in the container. You can find the mapped port by running docker port <container_name> or by inspecting the container’s network settings.
Mapping Multiple Ports
You can map multiple ports by specifying the -p flag multiple times:
docker run -p 8080:80 -p 8443:443 nginx
This will map port 80 in the container to port 8080 on the host, and port 443 in the container to port 8443 on the host.
Viewing Mapped Ports
You can view the mapped ports for a running container by using the docker port command:
docker port <container_name>
This will show you the mapping between the container ports and the host ports.
By understanding how to map ports between containers and the host system, you can ensure that your Docker-based applications are accessible from outside the container, allowing users and other systems to interact with your applications.
Configuring Port Forwarding in Docker Compose
Introducing Docker Compose
Docker Compose is a tool for defining and running multi-container Docker applications. It allows you to define your application’s services, networks, and volumes in a single YAML file, making it easier to manage and deploy your application.
Configuring Port Forwarding in Docker Compose
In a Docker Compose file, you can configure port forwarding using the ports directive. The syntax is similar to the docker run command:
version: "3"
services:
web:
image: nginx
ports:
- 8080:80
In this example, the web service is running the Nginx web server, and port 80 in the container is mapped to port 8080 on the host system.
You can also map multiple ports by specifying the ports directive multiple times:
version: "3"
services:
web:
image: nginx
ports:
- 8080:80
- 8443:443
This will map port 80 in the container to port 8080 on the host, and port 443 in the container to port 8443 on the host.
Dynamic Port Mapping
Similar to the docker run command, you can also use dynamic port mapping in Docker Compose by omitting the host port:
version: "3"
services:
web:
image: nginx
ports:
- 80
This will map an available port on the host system to port 80 in the container. You can find the mapped port by running docker-compose port web 80.
By configuring port forwarding in your Docker Compose file, you can ensure that your multi-container applications are accessible from outside the Docker environment, allowing users and other systems to interact with your applications.
Best Practices for Port Forwarding
Use Specific Host Ports
When possible, use specific host ports rather than relying on dynamic port mapping. This makes it easier to remember and access your applications, and can also simplify any firewall or network configuration that may be required.
Avoid Conflicting Ports
Make sure that the host ports you choose do not conflict with any other services or applications running on the host system. This can prevent port conflicts and ensure that your Docker-based applications can be accessed without issues.
Document Port Mappings
Clearly document the port mappings used by your Docker-based applications, both in your code and in any deployment or configuration documentation. This will make it easier for other developers or operations teams to understand and work with your applications.
Use Environment Variables for Port Configurations
Consider using environment variables to configure the port mappings for your Docker-based applications. This can make it easier to change the port configurations without having to modify the application code or Docker configuration files.
version: "3"
services:
web:
image: nginx
ports:
- ${WEB_PORT}:80
In this example, the WEB_PORT environment variable is used to configure the host port that the Nginx web server is mapped to.
Monitor and Manage Port Utilization
Regularly monitor the port utilization on your host systems to ensure that you are not running out of available ports for your Docker-based applications. Consider implementing automated tools or scripts to help manage and optimize port utilization.
By following these best practices, you can ensure that your Docker-based applications are accessible, secure, and easy to manage, making it easier to develop, deploy, and maintain your applications in a containerized environment.
Summary
In this comprehensive guide, you have learned the essentials of port forwarding in Docker containers. You now know how to expose ports, map them between containers and the host, and configure port forwarding in Docker Compose. By applying these techniques, you can ensure that your Docker-based applications are accessible from the outside world, enabling seamless integration and deployment. Remember to follow best practices for port forwarding to maintain a secure and efficient Docker environment.
