I have two docker images. one is a postgresql database and the other is a FastAPI. I tried running both using docker run
and it all works correctly. I can use 127.0.0.1:8000/docs
and access the Swagger UI. The problem starts when using docker compose.
Here my file:
services:
db:
image: postgres
# restart: always
environment:
POSTGRES_USER: my-user
POSTGRES_PASSWORD: password
ports:
- '5432:5432'
volumes:
- /var/lib/postgresql/data:/var/lib/postgresql/data
api:
image: api_rest
# restart: always
# links:
# - db
extra_hosts:
- "host.docker.internal:host-gateway"
ports:
- 8000:8000
The outputs seems Ok, as if both services are connecting. However, accessing 127.0.0.1:8000/docs
gives nothing. I understood that using ports
command should already expose the container IP with the host.
Doing some debugging I did docker container inspect <MY FASTAPI CONTAINER ID>
and got:
"Networks": {
"network_default": {
"IPAMConfig": null,
"Links": null,
"Aliases": [
"api",
"b9201abec1c2"
],
"MacAddress": "02:42:ac:15:00:03",
"NetworkID": "fbde8b8a0dc3ff02b24b9c59290dd7bb98256774c1e8e848beb577b77b7d7152",
"EndpointID": "00decc867548762ee60fa0db31c727fac80adf2fc5636060565ebaf5d64165b5",
"Gateway": "172.21.0.1",
"IPAddress": "172.21.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"DriverOpts": null,
"DNSNames": [
"fast-api-1",
"api",
"b9201abec1c2"
]
I therefore try both 172.21.0.1
and 172.21.0.3
but no luck.
BTW: the output of docker compose is:
Attaching to fast-api-1, postgres-db-1
postgres-db-1 |
postgres-db-1 | PostgreSQL Database directory appears to contain a database; Skipping initialization
postgres-db-1 |
postgres-db-1 | 2024-03-27 15:47:30.892 UTC [1] LOG: starting PostgreSQL 15.3 (Debian 15.3-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit
postgres-db-1 | 2024-03-27 15:47:30.892 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
postgres-db-1 | 2024-03-27 15:47:30.892 UTC [1] LOG: listening on IPv6 address "::", port 5432
postgres-db-1 | 2024-03-27 15:47:30.907 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
postgres-db-1 | 2024-03-27 15:47:30.947 UTC [29] LOG: database system was shut down at 2024-03-27 15:37:55 UTC
postgres-db-1 | 2024-03-27 15:47:30.973 UTC [1] LOG: database system is ready to accept connections
fast-api-1 | INFO: Will watch for changes in these directories: ['/']
fast-api-1 | INFO: Loading environment from 'api_rest/docker.env'
fast-api-1 | INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
fast-api-1 | INFO: Started reloader process [7] using WatchFiles
fast-api-1 | Connecting to database using postgresql+psycopg2://my-user:password@db:5432/postgres
fast-api-1 | INFO: Started server process [9]
fast-api-1 | INFO: Waiting for application startup.
fast-api-1 | INFO: Application startup complete.
The output of docker ps
4eca35c35e45 api_rest "/bin/sh -c 'uvicorn…" About a minute ago Up 3 seconds 0.0.0.0:8000->8000/tcp, :::8000->8000/tcp fast-api-1
280b95fd9257 postgres-db "docker-entrypoint.s…" 2 hours ago Up 3 seconds 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp postgres-db-1
I tried changing port to 127.0.0.1:8000:8000
because is the IP I use on my web browser but no luck. Also, the command of extra_hosts
I do not understand but it changes nothing.
Relevant information is:
Your problem is visible here:
fast-api-1 | INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
Uvicorn is running with the socket bound to the default host 127.0.0.1
, which is the localhost of the container, meaning that it will only accept traffic from within the container itself.
See for example this page for a complete example, but in short you need to do something along the lines of the following:
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", ...]
Using 0.0.0.0
as the host will accept traffic from outside of the container too.
You should also just remove the extra_hosts
, it's not needed. Then you should be able to connect from the host machine using 127.0.0.1:8000
just like that.