Setup
Consider this relatively simple docker-app using fastapi as server and couchdb as db.Here is the project structure
├── app.py
├── compose
│   ├── couchdb.Dockerfile
│   └── server.Dockerfile
├── docker-compose.yml
├── .env  # Global vars e.g. DB credentials
├── Pipfile  # For local dev
├── Pipfile.lock  # Same
└── requirements.txt
Here are is my app.py
import couchdb
from fastapi import FastAPI, HTTPException
import os
def _load_db_client():
    _user = os.environ["COUCHDB_USER"]
    _password = os.environ["COUCHDB_PASSWORD"]
    _host = os.environ["COUCHDB_HOST"]
    _port = os.environ["COUCHDB_PORT"]
    _client = couchdb.Server(f"http://{_user}:{_password}@{_host}:{_port}")
    del _user, _password, _host, _port
    return _client
def _get_or_create_db(_client: couchdb.Server, db_name: str) -> couchdb.Database:
    if db_name in _client:
        return _client[db_name]
    print("Creating DB", db_name)
    return _client.create(db_name)
couch: couchdb.Server = _load_db_client()
db_user = _get_or_create_db(_client=couch, db_name="user")
app = FastAPI()
And here are my docker files:
### docker-compose ###
version: "3.4"
# This help to avoid routing conflict within virtual machines:
networks:
  default:
    ipam:
      driver: default
      config:
        - subnet: 192.168.112.0/24
services:
  couchdb:
    restart: unless-stopped
    build:
      context: .
      dockerfile: compose/couchdb.Dockerfile
    expose:
      - 5984
    ports:
      - "59840:5984"
    env_file:
      - .env
  server:
    restart: unless-stopped
    build:
      context: .
      dockerfile: compose/server.Dockerfile
    expose:
      - 8080
    ports:
      - "8080:8080"
    env_file:
      - .env
### couchdb.Dockerfile ###
FROM couchdb:latest
### server.Dockerfile ###
FROM python:3.8
RUN apt-get update && apt-get -y install tmux nano
ADD ./requirements.txt /srv
WORKDIR /srv
RUN pip install --upgrade pip
RUN pip install -r ./requirements.txt
ADD . /srv
CMD uvicorn app:app --host 0.0.0.0 --port 8080 --reload
Problem
When building docker, the command starting the server inside docker (`uvicorn app:app ...`) fails because of the line `db_user = ...`.Here is the full error:
INFO:     Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
INFO:     Started reloader process [6] using statreload
Creating DB user
Process SpawnProcess-1:
Traceback (most recent call last):
File "/usr/local/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
    self.run()
File "/usr/local/lib/python3.8/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
File "/usr/local/lib/python3.8/site-packages/uvicorn/subprocess.py", line 62, in subprocess_started
    target(sockets=sockets)
File "/usr/local/lib/python3.8/site-packages/uvicorn/main.py", line 390, in run
    loop.run_until_complete(self.serve(sockets=sockets))
File "uvloop/loop.pyx", line 1456, in uvloop.loop.Loop.run_until_complete
File "/usr/local/lib/python3.8/site-packages/uvicorn/main.py", line 397, in serve
    config.load()
File "/usr/local/lib/python3.8/site-packages/uvicorn/config.py", line 278, in load
    self.loaded_app = import_from_string(self.app)
File "/usr/local/lib/python3.8/site-packages/uvicorn/importer.py", line 20, in import_from_string
    module = importlib.import_module(module_str)
File "/usr/local/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
File "", line 1014, in _gcd_import  File "", line 991, in _find_and_load
File "", line 975, in _find_and_load_unlocked
File "", line 671, in _load_unlocked
File "", line 783, in exec_module
File "", line 219, in _call_with_frames_removed
File "./app.py", line 24, in
     db_user = _get_or_create_db(_client=couch, db_name="user")
 File "./app.py", line 20, in _get_or_create_db
     return _client.create(db_name)
 File "/usr/local/lib/python3.8/site-packages/couchdb/client.py", line 221, in create
     self.resource.put_json(name)
 File "/usr/local/lib/python3.8/site-packages/couchdb/http.py", line 577, in put_json
     return self._request_json('PUT', path, body=body, headers=headers,
File "/usr/local/lib/python3.8/site-packages/couchdb/http.py", line 595, in _request_json
    status, headers, data = self._request(method, path, body=body,
File "/usr/local/lib/python3.8/site-packages/couchdb/http.py", line 590, in _request
    return self.session.request(method, url, body=body,
File "/usr/local/lib/python3.8/site-packages/couchdb/http.py", line 295, in request
    conn = self.connection_pool.get(url)
File "/usr/local/lib/python3.8/site-packages/couchdb/http.py", line 515, in get
    conn.connect()
File "/usr/local/lib/python3.8/http/client.py", line 921, in connect
    self.sock = self._create_connection(
File "/usr/local/lib/python3.8/socket.py", line 808, in create_connection
    raise err
File "/usr/local/lib/python3.8/socket.py", line 796, in create_connection
    sock.connect(sa)ConnectionRefusedError:
[Errno 111] Connection refused
My Guess
This error only occurs when building (`docker-compose up --build -d`): Once built, I can manually enter my server container execute the same command without any error. The user db is then created and my server up and running.Considering this, I suspect it might be the case that my couchdb container is not fully created when the server container tries to create the new db which yields the error.
Any ideas as to how solve this problem?
EDIT
# .env
COUCHDB_USER=admin
COUCHDB_PASSWORD=superSECRET!
COUCHDB_HOST=couchdb
COUCHDB_PORT=5984
 
    