Skip to content

Startup failures

The application container applies its migrations and then serves, and it takes itself down rather than answer against a schema or a configuration it does not match. Docker restarts it, so a stack that is misconfigured still looks alive: docker compose ps goes on reporting the app as Up, with its health check starting, because the container never lives long enough to fail one.

The status is not the signal, the log is:

Terminal window
docker compose logs app | tail -30

A stack whose .env still has an empty secret does not even get there: docker compose up refuses to interpolate the file and prints required variable SECRET_ENCRYPTION_KEY is missing a value: empty in .env; fill it with openssl rand -base64 32. It names every empty variable in one pass rather than one per run, so a .env copied and not edited prints all three at once, and POSTGRES_PASSWORD twice because both services read it. Fill them and run the command again; nothing is built until they are all there.

A port already taken stops just as early. docker compose up builds the image, starts the database, then prints failed to bind host port 0.0.0.0:8080/tcp: address already in use and stops there. The application container was created but never started, so docker compose logs app prints nothing at all and docker compose ps shows the database alone. Set WEB_PORT in .env to a free port, move PUBLIC_URL to the same one, and run the command again.

That last failure leaves a stack half up, and nothing says so. Compose starts the database first and the application after it, and it does not take the first back down when the second will not start: the command exits 1 having named only the container it stopped on, and the database goes on running.

Terminal window
docker compose ps # what survived the failure: the database, without the app

The application container survives too, and in a state worth knowing about. It was created and never started, and what failed was Docker attaching it to the network, so it is attached to none. Compose starts a container it has already created rather than building it again, so freeing the port by hand and repeating the same up starts that one: it comes up with no route to the database and loops on P1001: Can't reach database server at db:5432 while the database is running beside it.

Changing WEB_PORT and PUBLIC_URL avoids that, because an edit to .env is what makes compose replace the container. Freeing the port instead means clearing the half-started stack first:

Terminal window
docker compose down # containers and network gone; the volume and its data are not touched

Only down -v deletes what the database holds.

What the log says What it means
Invalid environment configuration: a variable is missing or malformed; the line under it names which one and what to run
SECRET_ENCRYPTION_KEY: must be 32 bytes base64-encoded openssl rand -hex 32 decodes to 48 bytes, not 32; that key wants openssl rand -base64 32
DATABASE_URL: is not a valid connection URL POSTGRES_PASSWORD holds a /, a ? or a #, which the connection URL reads as its own
P1001: Can't reach database server the database was not up yet, usually after a reboot; the restart clears it within seconds
P1000: Authentication failed against database server POSTGRES_PASSWORD was changed after the first start; the database still holds the old one

Putting the old password back is the way out of that last one.

Privacy