New docker installation and cannot log in - what am I doing wrong?

Version ie <v5.10.30>Running InvoiceNinja Docker:Latest

Environment <Docker/Shared Hosting/Zip/Other>Self hossted Debain 12 with Docker installed.

Checklist

  • Can you replicate the issue on our v5 demo site https://demo.invoiceninja.com or Invoice Ninja? No -
  • Have you searched existing issues? Yes
  • Have you inspected the logs in storage/logs/laravel.log for any errors? storage/logs directory is empty

Describe the bug

Hello,
I am attempting to setup InvoiceNinja on a Debian 12 system using the Docker image from invoiceninja/invoiceninja-debian - Docker Image
I have followed the instructions listed on this page, downloading the git image first, creating the APP_KEY and updating the IN_USER_EMAIL and IN_PASSWORD fields as required.
I have Apache2 running as a reverse proxy to the Invoice Ninja docker image and I can successfully bring up the login page when I connect to my URL.
However, I can not log on using either the credentials given in the IN_* environment variables or even the default “[email protected]”.

Steps To Reproduce

I have followed the exact steps listed on the Docker Hub page given above,

Expected Behavior

I should be able to log in

Additional context

I have tried this multiple times, deleting/removing the containers and images and trying with my own credentials for IN_USER_EMAIL and IN_PASSWORD and also leaving the defulat ones there but I get the same result every time.
I have also tried using the Android App and repeatedly get the “400 - Bad Request. These credentials do not match our records” response

Screenshots

Logs

No logs are being produced. I have checked in the invoiceninja/invoiceninja-debian container and nothing is there.

I would appreciate some advice on how to further test this and check what the problem could be?

Many thanks

Hi,

Can you access the users table in the database to check if there’s a user and what email is set?

Hello Hillel

Thanks for geting back.

I have used docker run --rm -it invoiceninja/invoiceninja-debian /bin/bash to open a bash shell in the only ninja container I can see on my server. However, once in, I can’t seem to connect to the MySQL server via the command line.

Trying to use the mysql cli to attach to the ninja MySQL database keeps throwing the following error

ERROR 2002 (HY000): Can’t connect to local server through socket ‘/run/mysqld/mysqld.sock’ (2)

I have also tried connecting to the IP address of the mysql database (used docker inspect to find it) but that just hangs.

Could you please confirm the correct mysql command to use to connect to the mysql container within Ninja?

Thank you

Ciaran

Maybe this AI answer will help:

The issue here is that when you run docker run --rm -it invoiceninja/invoiceninja-debian /bin/bash, you are actually spinning up a brand new, isolated temporary container that only lives for that session. It cannot see the MySQL server on the standard localhost or socket because they are running in a completely different container.

To connect to your existing MySQL database, you need to execute a command inside your already running MySQL container, rather than the app container.

Here is how you can do it:

1. Find your MySQL container name

First, list your running containers to find the exact name or ID of your MySQL/MariaDB container:

Bash

docker ps

Look for the container running the mysql or mariadb image.

2. Connect directly to the MySQL CLI

Instead of launching a bash shell and then running MySQL, you can use docker exec to jump straight into the MySQL CLI of that running database container.

Run the following command (replace your_mysql_container_name with the actual name/ID from step 1):

Bash

docker exec -it your_mysql_container_name mysql -u root -p

  • Note: If you set up a specific user for Invoice Ninja (e.g., ninja), you can replace -u root with -u ninja and enter the corresponding password when prompted.

Alternative: Connecting from the Ninja App Container

If you absolutely need to connect from within an app container for testing, you need to use docker exec on your existing app container (not docker run) and specify the MySQL container’s network name as the host:

Bash

docker exec -it your_invoiceninja_container_name /bin/bash

Once inside, you must explicitly target the database host using the -h flag, as it won’t be available on localhost:

Bash

mysql -h your_mysql_container_name -u ninja -p

Hello Hillel

Thank you - finally able to access the database.

In answer to your original question, there is exactly one row in the users table and it is indeed the user details I provided for the IN_USER_EMAIL setting in the .env file.

Grateful for advice on how to futher debug why I can’t log in.

Ciaran

Hello again Hillel,

I realise now, from your reply above, that when I ran the docker command I quoted above, that I am not seeing the proper app container.

Having run docker exec -it debian-app-1 /bin/bash I can now see that I have a file in the storage/logs folder and its contents are as follows:-

[previous exception] [object] (PDOException(code: 2002): SQLSTATE[HY000] [2002] Connection refused at /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:67)
[stacktrace]
#0 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php(67): PDO::connect()
#1 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php(85): Illuminate\Database\Connectors\Connector->createPdoConnection()
#2 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php(48): Illuminate\Database\Connectors\Connector->tryAgainIfCausedByLostConnection()
#3 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connectors/MySqlConnector.php(24): Illuminate\Database\Connectors\Connector->createConnection()
#4 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connectors/ConnectionFactory.php(186): Illuminate\Database\Connectors\MySqlConnector->connect()
#5 [internal function]: Illuminate\Database\Connectors\ConnectionFactory->{closure:Illuminate\Database\Connectors\ConnectionFactory::createPdoResolverWithHosts():181}()
#6 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php(1257): call_user_func()
#7 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php(1295): Illuminate\Database\Connection->getPdo()
#8 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php(525): Illuminate\Database\Connection->getReadPdo()
#9 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php(420): Illuminate\Database\Connection->getPdoForSelect()
#10 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php(827): Illuminate\Database\Connection->{closure:Illuminate\Database\Connection::select():411}()
#11 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php(999): Illuminate\Database\Connection->runQueryCallback()
#12 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php(978): Illuminate\Database\Connection->tryAgainIfCausedByLostConnection()
#13 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php(796): Illuminate\Database\Connection->handleQueryException()
#14 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php(411): Illuminate\Database\Connection->run()
#15 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php(357): Illuminate\Database\Connection->select()
#16 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php(374): Illuminate\Database\Connection->selectOne()
#17 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Schema/Builder.php(176): Illuminate\Database\Connection->scalar()
#18 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Migrations/DatabaseMigrationRepository.php(185): Illuminate\Database\Schema\Builder->hasTable()
#19 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php(758): Illuminate\Database\Migrations\DatabaseMigrationRepository->repositoryExists()
#20 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/MigrateCommand.php(164): Illuminate\Database\Migrations\Migrator->repositoryExists()
#21 /var/www/html/vendor/laravel/framework/src/Illuminate/Support/helpers.php(328): Illuminate\Database\Console\Migrations\MigrateCommand->{closure:Illuminate\Database\Console\Migrations\MigrateCommand::repositoryExists():164}()
#22 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/MigrateCommand.php(164): retry()
#23 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/MigrateCommand.php(140): Illuminate\Database\Console\Migrations\MigrateCommand->repositoryExists()
#24 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/MigrateCommand.php(110): Illuminate\Database\Console\Migrations\MigrateCommand->prepareDatabase()
#25 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php(671): Illuminate\Database\Console\Migrations\MigrateCommand->{closure:Illuminate\Database\Console\Migrations\MigrateCommand::runMigrations():109}()
#26 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/MigrateCommand.php(109): Illuminate\Database\Migrations\Migrator->usingConnection()
#27 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/MigrateCommand.php(88): Illuminate\Database\Console\Migrations\MigrateCommand->runMigrations()
#28 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(36): Illuminate\Database\Console\Migrations\MigrateCommand->handle()
#29 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Util.php(43): Illuminate\Container\BoundMethod::{closure:Illuminate\Container\BoundMethod::call():35}()
#30 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(96): Illuminate\Container\Util::unwrapIfClosure()
#31 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(35): Illuminate\Container\BoundMethod::callBoundMethod()
#32 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php(799): Illuminate\Container\BoundMethod::call()
#33 /var/www/html/vendor/laravel/framework/src/Illuminate/Console/Command.php(211): Illuminate\Container\Container->call()
#34 /var/www/html/vendor/symfony/console/Command/Command.php(341): Illuminate\Console\Command->execute()
#35 /var/www/html/vendor/laravel/framework/src/Illuminate/Console/Command.php(180): Symfony\Component\Console\Command\Command->run()
#36 /var/www/html/vendor/symfony/console/Application.php(1117): Illuminate\Console\Command->run()
#37 /var/www/html/vendor/symfony/console/Application.php(356): Symfony\Component\Console\Application->doRunCommand()
#38 /var/www/html/vendor/symfony/console/Application.php(195): Symfony\Component\Console\Application->doRun()
#39 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(198): Symfony\Component\Console\Application->run()
#40 /var/www/html/artisan(35): Illuminate\Foundation\Console\Kernel->handle()
#41 {main}
"}

Does this give you a better clue as to what is going wrong?

Ciaran

The stack trace from your logs explains exactly why you can’t log in: SQLSTATE[HY000] [2002] Connection refused.

Even though you can connect to the database manually using Docker commands, the Invoice Ninja web app itself is failing to talk to the MySQL container. When the app tries to verify your login credentials, the database connection fails, resulting in a login error.

Here is how to fix this:

1. Check your .env Database Host

In a standard Docker Compose setup, containers cannot communicate using localhost or 127.0.0.1. They need to use the name of the database service defined in your docker-compose.yml file.

Open your .env file and look for the DB_HOST variable.

  • Incorrect: DB_HOST=127.0.0.1 or DB_HOST=localhost

  • Correct: It should match the exact service name of your database container (often db, mysql, or mariadb).

For example, if your database service is named db in your compose file, your .env should look like this:

Code snippet

DB_HOST=db

2. Verify the Docker Network

If DB_HOST is already correct, the two containers might not be on the same Docker network, or the database container isn’t fully healthy when the app tries to connect.

You can verify they can see each other by jumping back into your app container and trying to ping the database host:

Bash

docker exec -it debian-app-1 /bin/bash
# Once inside, try to ping or curl the DB host name (e.g., db)
ping db

3. Restart the Setup

After making any changes to your .env file, make sure to recreate the containers so the new configuration takes effect:

Bash

docker compose down
docker compose up -d

Morning HillelDB connection

Thank you for the tips. Unfortunately, I am no further forward.

DB Contents of .env file

DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=ninja
DB_USERNAME=ninja
DB_PASSWORD=ninja
DB_ROOT_PASSWORD=ninjaAdm1nPassword
DB_CONNECTION=mysql,

DB definition on compose file

mysql:
image: mysql:8
restart: unless-stopped
environment:
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_USER: ${DB_USERNAME}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
healthcheck:
test:
[
“CMD”,
“mysqladmin”,
“ping”,
“-h”,
“localhost”,
“-u${MYSQL_USER}”,
“-p${MYSQL_PASSWORD}”,
]

So, if I am reading your advice above, the DB_HOST in the .env file does match the db service name in the compose file.

However, if I docker exec into the app container and try the ping command, it responds that the ping command cannot be found. I’ve searched the file system and cannot find it either so it’s not a path problem and as you suggest a Docker Network issue.

Also tried to install to use curl to test connectivity and this is the result I got:

root@994602f36808:/var/www/html# curl -v mysql:3306

  • Host mysql:3306 was resolved.
  • IPv6: (none)
  • IPv4: 172.27.0.2
  • Trying 172.27.0.2:3306…
  • Connected to mysql (172.27.0.2) port 3306
  • using HTTP/1.x

GET / HTTP/1.1
Host: mysql:3306
User-Agent: curl/8.14.1
Accept: /

  • Request completely sent off
  • Received HTTP/0.9 when not allowed
  • closing connection #0
    curl: (1) Received HTTP/0.9 when not allowed
    root@994602f36808:/var/www/html#

So from what I can see, the app container can resolve the database container by name (mysql) and the settings in the .env and compose file match, but I’m still getting the problem.

Your advice is gratefully appreciated.

Ciaran

Sorry I’m not sure, you may want to try a clean install to see if it helps.

The env-file isn’t declared in the MySQL section, is it?

try “docker compose config” and check if the enviroment inside the mysql-part is filled correct.

Also check the healthcheck… there are other env-vars in use

Hi

I think the .env file is correctly referred to as the output of the “docker conpose config” command shows the changes I make to the .env file have propogated through.

THe only thing I can see is that the network name associated with the app/nginx/mysql bits all say “default: null” but the name of the network in the Network section at the bottom of the file says “debian_default” - I don’t know if this is important or not.

The output of the docker compose config command is

name: debian
services:
app:
build:
context: /dockerfiles/debian
dockerfile: Dockerfile
depends_on:
mysql:
condition: service_healthy
required: true
redis:
condition: service_healthy
required: true
environment:
APP_DEBUG: “true”
APP_ENV: production
APP_KEY: <APP_KEY>
APP_URL: http://localhost:8012
CACHE_DRIVER: redis
DB_CONNECTION: mysql
DB_DATABASE: ninja
DB_HOST: mysql
DB_PASSWORD: ninja
DB_PORT: “3306”
DB_ROOT_PASSWORD: ninjaAdm1nPassword
DB_USERNAME: ninja
FILESYSTEM_DISK: debian_docker
IN_PASSWORD:
IN_USER_EMAIL: <INITIAL_ACCOUNT_EMAIL>
IS_DOCKER: “true”
MAIL_ENCRYPTION: “null”
MAIL_FROM_ADDRESS: <FROM_EMAIL_ADDRESS>
MAIL_FROM_NAME: <MAIL_FROM_NAME>
MAIL_HOST: <EMAIL_SERVER>
MAIL_MAILER: log
MAIL_PASSWORD: <EMAIL_PASSWORD>
MAIL_PORT: “587”
MAIL_USERNAME: <EMAIL_USERNAME>
MYSQL_DATABASE: ninja
MYSQL_PASSWORD: ninja
MYSQL_ROOT_PASSWORD: ninjaAdm1nPassword
MYSQL_USER: ninja
NORDIGEN_SECRET_ID: “”
NORDIGEN_SECRET_KEY: “”
PDF_GENERATOR: snappdf
PHANTOMJS_PDF_GENERATION: “false”
QUEUE_CONNECTION: redis
REDIS_HOST: redis
REDIS_PASSWORD: “null”
REDIS_PORT: “6379”
REQUIRE_HTTPS: “false”
SCOUT_DRIVER: “null”
SESSION_DRIVER: redis
TRUSTED_PROXIES: ‘*’
image: invoiceninja/invoiceninja-debian:latest
networks:
default: null
restart: unless-stopped
volumes:

  • type: volume
    source: app_public
    target: /var/www/html/public
    volume: {}
  • type: volume
    source: app_storage
    target: /var/www/html/storage
    volume: {}
    mysql:
    environment:
    MYSQL_DATABASE: ninja
    MYSQL_PASSWORD: ninja
    MYSQL_ROOT_PASSWORD: ninjaAdm1nPassword
    MYSQL_USER: ninja
    healthcheck:
    test:
  • CMD
  • mysqladmin
  • ping
  • -h
  • localhost
  • -uninja
  • -pninja
    image: mysql:8
    networks:
    default: null
    restart: unless-stopped
    volumes:
  • type: volume
    source: mysql_data
    target: /var/lib/mysql
    volume: {}
    nginx:
    depends_on:
    app:
    condition: service_healthy
    required: true
    image: nginx:alpine
    networks:
    default: null
    ports:
  • mode: ingress
    target: 80
    published: “8300”
    protocol: tcp
    restart: unless-stopped
    volumes:
  • type: bind
    source: /dockerfiles/debian/nginx
    target: /etc/nginx/conf.d
    read_only: true
    bind: {}
  • type: volume
    source: app_public
    target: /var/www/html/public
    read_only: true
    volume: {}
  • type: volume
    source: app_storage
    target: /var/www/html/storage
    read_only: true
    volume: {}
    redis:
    healthcheck:
    test:
  • CMD
  • redis-cli
  • ping
    image: redis:alpine
    networks:
    default: null
    restart: unless-stopped
    volumes:
  • type: volume
    source: redis_data
    target: /data
    volume: {}
    networks:
    default:
    name: debian_default
    volumes:
    app_public:
    name: debian_app_public
    driver: local
    app_storage:
    name: debian_app_storage
    driver: local
    mysql_data:
    name: debian_mysql_data
    driver: local
    redis_data:
    name: debian_redis_data
    driver: local

.I will try blowing this installation away and remove any docker images that have been downloaded to try the fresh installation as suggested by Hillel but I’m not sure this will change anything.

I only make two changes to the default files as installed by the git clone command and these are:-

  1. In the compose yml file, I change the ports definition for the nginx container from “80:80” to “8300":80” as port 80 is already in use on my server.
  2. I edit the .env file to add the APP_KEY and the IN_USER_EMAIL/IN_PASSWORD settings for the initial user.

Note that I have Apache on my server and it’s configured as a reverse proxy. The virtual host configuration specifically points to port 8300.

Again any thoughts are gratefully appreciated.

Please use for Outputs the Code-Format (Preformated text)

if your reverse proxy works correct, then the APP_URL is the address configured in the reverse-proxy. In my case without any Port (https://..)