There is no information online on how to access a docker compose application from the internet

Running docker compose up works, and the application can be accessed from the host machine.

However, I need to access the application from the internet. This is a website. I need to type the name of the website in a browser, anywhere in the world, and access the docker composer application.

This is a basic, basic feature and requirement. This is the main reason for someone to use docker, to build websites. However, there is no information anywhere in the documentation on how to access the application from the internet.

Hello and welcome,

this is not special to Docker - this is a generic request.

  • Your webserver has to be accessible from the internet - which means it needs be accessible on a public IP-address. This might be due to tha fact that it is directly connected to the internet and therefore has a public IP-address or you have some device (directly connected to the internet) which forwards the requests to your webserver. This device might be a reverse-proxy-server or a router doing some port-forwarding.
  • You need a DNS-entry pointing to the public IP-address of your (Docker-)Webserver-Host (or the public IP-address of your router/reverse proxy mentioned above).
  • You need good knowledge about IT-security to not expose other ports/services to the public internet than absolutely needed for your service and to secure your application and your server and network against attacks (e.g. XSS, SQL-Injection, escalation of rights, …).

All these points are not special to Docker - they are the same for a bare-metal-webserver (a webserver running directly on the host-OS).

Hi @matthiasradde .

I followed all of those steps, as I worked as a software developer my entire life, and deployed hundreds of applications. In this exact same virtual machine, I can deploy any applications, like php, flask, rails, node, etc. However, docker compose applications are not visible outside of the local host. So the problem is necessarily docker-compose specific. Also, the same problem didn’t happen before with the snap version of docker. So it is really fundamental that the docker compose documentation provides basic instructions on how to expose a docker composer application to the internet. Since there is absolutely no information anywhere, I cannot even redo step-by-step, or debug, since docker composer in this regard is an undocumented black box.

Hello,

I use the following docker-compose.yml to run a webserver accessible from other computers on ports 3080 and 3443. docker-compose will create a separate network for every docker-compose.yml unless specified otherwise (network_mode: ...). But there is no need to run it on the host-network.

version: "3.2"

services:
  nginx:
    image: nginx:latest
    ports:
      - "3080:80"
      - "3443:443"
    volumes:
      - "/srv/www/html:/var/www/html"
      - ./default.conf:/etc/nginx/conf.d/default.conf
      - ./ssl:/etc/nginx/ssl
    extra_hosts:
      - "centrino2-tomcat:172.17.0.1"
    links:
      - php
  php:
    build: ./build-php

If you run Docker on Windows you may have to fight with the Windows-integrated firewall to have this thing accessible from other computers (= the whole internet in your case :slight_smile: ).

From my point of view docker-compose is documented but there is the caveat that some options within the docker-compose.yml are not available for all versions - but if you try to use the wrong version it will complain about it :slight_smile:.
It might be a good idea to provide your docker-compose.yml so that others may check if there is something missing?
You can also check with docker ps -a which containers are running and provide/expose which port to the outer world (see column PORTS from docker ps -a-output). You may also check in which network the container is (docker container inspect ...)

Please provide the output of docker version and docker info, so we can understand what platform we are dealing with here.

To provide additional explanation on what I would expect from Docker documentation, you can see here an example for the Flask project:

https://flask.palletsprojects.com/en/2.2.x/quickstart/

The “Externally Visible Server” section explicitly provides a set of instructions regarding what I should do to have an externally visible server, and what to expect, instead of going with “this is not flask specific”. I would expect the docker composer documentation to provide something similar.

In fact, doing that on the exact same machine leads to the Flask app being visible externally. Docker apps, however, are not externally visible with similar setup.

Moreover, Docker Compose worked fine with the snap version of Docker. I had some issues with that later on and had to uninstall and install again, and then I preferred to follow the official installation instructions for ubuntu. Unfortunately this forum doesn’t allow me to add the link in here.

So I guess my docker version and info would be the same as anyone following those instructions. The docker version gives:

"Client: Docker Engine - Community
Version: 23.0.2
API version: 1.42
Go version: go1.19.7
Git commit: 569dd73
Built: Mon Mar 27 16:16:27 2023
OS/Arch: linux/amd64
Context: default

Server: Docker Engine - Community
Engine:
Version: 23.0.2
API version: 1.42 (minimum version 1.12)
Go version: go1.19.7
Git commit: 219f21b
Built: Mon Mar 27 16:16:27 2023
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.19
GitCommit: 1e1ea6e986c6c86565bc33d52e34b81b3e2bc71f
runc:
Version: 1.1.4
GitCommit: v1.1.4-0-g5fd4c4d
docker-init:
Version: 0.19.0
GitCommit: de40ad0"

and the docker info gives:

Client:
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.10.4
Path: /usr/libexec/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v2.17.2
Path: /usr/libexec/docker/cli-plugins/docker-compose
scan: Docker Scan (Docker Inc.)
Version: v0.23.0
Path: /usr/libexec/docker/cli-plugins/docker-scan

Server:
Containers: 3
Running: 0
Paused: 0
Stopped: 3
Images: 3
Server Version: 23.0.2
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Using metacopy: false
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: systemd
Cgroup Version: 2
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 1e1ea6e986c6c86565bc33d52e34b81b3e2bc71f
runc version: v1.1.4-0-g5fd4c4d
init version: de40ad0
Security Options:
apparmor
seccomp
Profile: builtin
cgroupns
Kernel Version: 5.19.0-35-generic
Operating System: Ubuntu 22.10
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 7.763GiB
Name: ubuntu-s-1vcpu-512mb-10gb-nyc1-01
ID: 3b4736ac-36ef-49c9-b7b1-9eb4252aecbd
Docker Root Dir: /var/lib/docker
Debug Mode: false
Registry: https://index.docker.io/v1/
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false

My docker-compose file is as simple as possible:

services:
frontend:
build: ./frontend
ports:
- 3000:3000

with a React frontend and, as stated, it works fine for the localhost. I have also tried:

services:
frontend:
build: ./frontend
ports:
- 0.0.0.0:3000:3000

but nothing changed.

Now we know its Docker-ce 23.0.2 on Ubuntu 20.10. This is a cruical information, as we now know that Docker Desktop is not used - and the restrictions that apply to it don’t apply in this scenario.

This is sufficient, as by default docker publishes the host port to 0.0.0.0.

It should work,

  • If the host has a public ip, the published port is already bound to it,
  • if a loadbalaner with a public ip forwards traffic to one of the hosts lan ip’s it can reach (routing ok, no firwall that prevents it).
  • If your public ip is natted into a private ip-range and a specific port of the public ip is forwarded to one of the hosts ip’s on port 3000…

There is nothing special about where the traffic originates from, regardless whether itÄs from the docker host itself, from one of the lan’s it is connected to, or if the traffic is routed through the internet and reaches your host by routing or port forwarding: it works. So what exactly would a documentation for something that doesn’t need to be configured look like? Docker documents how to publish container ports to host ports. Everything else depends on the network and solution design.

Is the flask application inside the container also bound to 0.0.0.0? Otherwise, the published host port will reach nothing. Localhost of the host is not the same localhost of the container.

If it works with http://localhost:3000, but not with http://host-ip:3000, then something else is going on which you need to find out. For instance cloud providers use security groups attached to compute instances, some vm solutions use the same. Though, this shouldn’t be a thing on bare metal machines,.

1 Like

This is DEFINITELY a bug on Docker, because I resolved it by removing the apt-get version of docker and installing the snap version:

apt-get remove docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
snap install docker

So the issue does not happen with the snap version, but it happens with the officially recommended version for ubuntu on the docker site!

I opened a ticket regarding this on github, but I don’t know if they’ll give any attention!

Anyway I guess this won’t affect me, since I’ll use the snap version from now on! But it definitely affects other users!