I'm trying to run docker swarm on a single node and having trouble getting a docker app port exposed to the host.
This is similar Docker swarm service port not exposed but I'm running in a single node, and provide more detail on my question and research.
For example, given the following myapp.yml file:
version: "3"
services:
app:
image: myapp
ports:
- "8123:8123"
The stack is started via
docker stack deploy -c myapp.yml myapp
After the stack is started, when I try to access the port (via curl) it fails. For example,
curl -v http://localhost:8123/myapp
shows the connection was refused (nothing was listening on that port).
The following command starts the image and shows how to verify the port is exposed.
docker run -p 8123:8123 --name myapp myapp
Curl then works.
curl -v http://localhost:8123/myapp
Gives output from the app running in docker.
When I run docker ps
the output in the PORTS section shows: 0.0.0.0:8123:8123/tcp
.
docker.network inspect bridge
- Show that the docker container is assigned to the bridge .network. The docker bridge.network is used by default with the docker run command.
The command docker port myapp
shows:
8123/tcp -> 0.0.0.0:8123
which matches the output from docker ps
PORT field.
After starting using docker stack deploy -c myapp.yml myapp
, I run the docker ps
command and only see 8123/tcp
in the PORTS field of the output.
The command docker port myapp
has no output (indicating no ports are available from the docker host.
When I run docker.network ls
, I see:
NETWORK ID NAME DRIVER SCOPE
1234567890 bridge bridge local
9999999999 myapp_default overlay swarm
So I noticed that the.network myapp_default is in a different mode than bridge, local. I tried using existing bridge .network but when I refereed to the bridge .network in my stack/compose file I observed that the.network myapp_bridge was created.
So I read up on docker.networking https://blog.alexellis.io/docker-stacks-attachable.networks/ was a good writeup.
So far I haven't gotten it to work so I drafted this to ask for suggestions/help.
NOTE: This aricle (dated Feb 2017) says it should work but doesn't address my question.
I think I'm close.
https://docs.docker.com/v17.12/get-started/part5/ - is the docker primary documentation for the docker stack technology. But searches on that page for.networks shows nothing useful.
https://blog.alexellis.io/docker-stacks-attachable.networks/ - Good write up.
Docker swarm service port not exposed - similar to the question I'm asking.
https://runnable.com/docker/basic-docker.networking - Write up on docker.networking. It says the following when creating an overlay.network (which is the default when docker stack deploy is used).
These.networks require a valid key-value store service, such as Consul, Etcd, or ZooKeeper. You must install and configure your key-value store service before creating your.network.
Can not use user-defined bridge in swarm compose yaml file .
In swarm
ports:
- "8123:8123"
will expose port on all swarm nodes and in case of use of the port on some of the nodes by another service you can have problems
you can expose port only on host with container with next docker-compose.yml config
services:
app:
ports:
- target: 8123
published: 8123
mode: host
You should define a network for your services. In Docker Swarm mode, the docker container becomes 'Service', to access its port, you call to the Service's name I provide you an example of docker-compose file how to connect nginx and php-fpm
version: '3.2'
services:
nginx:
image: nginx
links:
- php
- mariadb:mysql
ports:
- "8880:80"
networks:
- frontend
deploy:
#mode: replicated
replicas: 1
placement:
constraints: [node.role == manager]
php:
image: php
deploy:
#mode: replicated
replicas: 1
placement:
constraints: [node.role == manager]
#endpoint_mode: dnsrr
links:
- mariadb:mysql
mariadb:
image: mariadb:10.4.1
#restart: always
deploy:
mode: replicated
replicas: 1
#placement:
#constraints: [node.role == manage]
environment:
MYSQL_ROOT_PASSWORD: SECRET
volumes:
- type: volume
source: mydatabase
target: /var/lib/mysql/data
volume:
nocopy: true # do not copy data from container when a volume is created?
networks:
frontend
volumes:
mydatabase:
After you deployed (docker stack deploy -c docker-compose.yaml)
, to see list of Services:
docker service ls
To guild nginx how to access your php-fpm backend, edit your nginx configuration file :
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass **NAME_OF_PHP_SERVICE_IN SWARM**:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
Instead of putting your container's IP address ( IP:9000 ) , you put the name of the php Service in your Swarm cluster
I had a port that was being used in both a SWARM and on the local Linux OS, both apps ran but only one received the incoming connections.
What was strange is that no EADDRINSE error occurred when I would have expected an error to have occurred for one of the apps that was trying to use the port.
So for example, running local app on port 8080, and using a SWARM on this host using port 8080.
An incoming connection comes to port 8080, the connection was sent to one of them (I can't remember which).
I has same problem. Solved by changing IP. First, get the current docker swarm node IP address.
docker info
Find you IP Manager Addresses
row. For example, my IP was 192.168.0.13
. And now you can open your application by this address 192.168.0.13:8123
.
I had the same issue - on my ubuntu machine it was working - on my debian server not. Finally I got it narrowed to to the kernel version used on debian. Upgrading to 5.11.22-5 fixed the issue for me.
There have been posts about missing kernel modules (without mentioning which) - maybe that's related.
This frequently happens because of IPv6. On the host, localhost
is defined as ::1
rather than 127.0.0.1
in /etc/hosts
. Ingress.networking in swarm does not support IPv6 . So there are two possible solutions:
Connect using IPv4: curl -v http://127.0.0.1:8123/myapp
.
Publish the port using host mode rather than ingress.networking. This publishes the port only on the host where the containers are running. This can be useful for services that are deployed on every node ( deploy: mode: global
) to remove extra.networking hops between nodes. To switch to host mode for the published port, follow Ryabchenko Alexander's advice by switching to the long syntax when publishing your port:
ports: - target: 8123 published: 8123 mode: host
More details are in the compose file v3 reference: https://docs.docker.com/compose/compose-file/compose-file-v3/#long-syntax-1 . Note that publishing the port in host mode here is different from host.networking that runs the container without a.network sandbox, sadly "host" is used for two different things here, one being outside of swarm, and the other being outside of docker isolation.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.