Docker Deploy Invoice Ninja
The easiest way to deploy Invoice Ninja is through docker which I will show you below. However if you wish to manually deploy it, this guide might be useful.
I managed to deploy on a VM with only 512 MB of RAM. However, because we will be using a database container, and MySQL has a habbit of growing in memory, I would recommend deploying on a 1GB instance.
Grab the example.
#!/bin/bash mkdir -p $HOME/invoice-ninja/src git clone https://github.com/invoiceninja/dockerfiles.git $HOME/invoice-ninja/src/. mv $HOME/invoice-ninja/src/docker-compose/.env.example $HOME/invoice-ninja/env mv $HOME/invoice-ninja/src/docker-compose/nginx.conf $HOME/invoice-ninja/nginx.conf mv $HOME/invoice-ninja/src/docker-compose/docker-compose.yml $HOME/invoice-ninja/. rm -rf $HOME/invoice-ninja/src/
You should now have a folder called
invoice-ninja in your home directory which contains the following files:
Edit Environment Variables
The env file will look like below (unless it has changed since I wrote this tutorial).
MYSQL_DATABASE=ninja MYSQL_ROOT_PASSWORD=pwd APP_DEBUG=0 APP_URL=http://localhost:8000 APP_KEY=SomeRandomStringSomeRandomString APP_CIPHER=AES-256-CBC DB_USERNAME=root DB_PASSWORD=pwd DB_HOST=db DB_DATABASE=ninja MAIL_HOST=mail.service.host MAIL_USERNAME=username MAIL_PASSWORD=password MAIL_DRIVER=smtp MAIL_FROM_NAME="My name" MAIL_FROM_ADDRESSfirstname.lastname@example.org
Run the following script to set random passwords in the env file:
#!/bin/bash DB_PASSWORD=`openssl rand -base64 12` APP_KEY=`openssl rand -base64 24` FILEPATH="$HOME/invoice-ninja/env" # Update the app key SEARCH="APP_KEY=SomeRandomStringSomeRandomString" REPLACE="APP_KEY=$APP_KEY" sed -i "s;$SEARCH;$REPLACE;" $FILEPATH # Update mysql root password SEARCH="MYSQL_ROOT_PASSWORD=pwd" REPLACE="MYSQL_ROOT_PASSWORD=$DB_PASSWORD" sed -i "s;$SEARCH;$REPLACE;" $FILEPATH # Update app db password setting to be the same SEARCH="DB_PASSWORD=pwd" REPLACE="DB_PASSWORD=$DB_PASSWORD" sed -i "s;$SEARCH;$REPLACE;" $FILEPATH
It's very important to change the the following:
- Change the
APP_URLto your hostname or IP and remove the
- Update the
MAIL_items to your SMTP details.
It is important to ensure the following is the case:
APP_KEYhas been updated to a random string. E.g should not be:
MYSQL_ROOT_PASSWORDhave been updated to a random string and not set to
By the end of it, you should have something like:
MYSQL_DATABASE=ninja MYSQL_ROOT_PASSWORD=Htw0GOdwCF6NNt3E APP_DEBUG=0 APP_URL=http://invoices.mydomain.com APP_KEY=rfQH/9dZTjO4v4gARlnTz4oBrgin28qD APP_CIPHER=AES-256-CBC DB_USERNAME=root DB_PASSWORD=Htw0GOdwCF6NNt3E DB_HOST=db DB_DATABASE=ninja MAIL_HOST=smtp.gmail.com MAIL_USERNAMEemail@example.com MAIL_PASSWORD=myAppSpecificPassword MAIL_DRIVER=smtp MAIL_FROM_NAME="Programster Blogs" MAIL_FROM_ADDRESSfirstname.lastname@example.org
Now go into your
docker-compose.yml file and change:
- the database password to match whatever you set in the env file in the previous step.
- the port line from
- This will allow the site to be available without needing to enter a port into the URL bar.
You should end up with a docker-compose file that looks like the following:
version: '3.6' volumes: db: storage: logo: public: # uncomment if you want to use external network (example network: "web") #networks: # web: # external: true services: db: image: mysql:5 env_file: env restart: always volumes: - db:/var/lib/mysql networks: - default app: image: invoiceninja/invoiceninja env_file: env restart: always depends_on: - db volumes: - storage:/var/www/app/storage - logo:/var/www/app/public/logo - public:/var/www/app/public networks: - default web: image: nginx:1 volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro - storage:/var/www/app/storage - logo:/var/www/app/public/logo - public:/var/www/app/public expose: # Expose ports without publishing them to the host machine - theyâ€™ll only be accessible to linked services. - "80" depends_on: - app ports: # Delete if you want to use reverse proxy - 80:80 networks: # - web # uncomment if you want to use external network (reverse proxy for example) - default cron: image: invoiceninja/invoiceninja env_file: env volumes: - storage:/var/www/app/storage - logo:/var/www/app/public/logo - public:/var/www/app/public entrypoint: | bash -c 'bash -s <<EOF trap "break;exit" SIGHUP SIGINT SIGTERM sleep 300s while /bin/true; do ./artisan ninja:send-invoices ./artisan ninja:send-reminders sleep 1d done EOF' networks: - default
Now you can deploy with the following command:
Web UI Setup
Now navigate to your server's IP or hostname and you should be presented with a form to fill in like below:
Most of the details should already be filled in for you (from the environment file earlier). You just need to enter your name details and submit.
It would be a good idea to make use of button to send a test email to check your SMTP details are correct.
All state is held in the docker volumes called: * db * storage * logo * public
You will have seen these at the top of the docker-compose file section like so:
volumes: db: storage: logo: public:
You can use the
docker volume commands to interact with them. E.g. list them with:
docker volume ls
The actual data will default to being located under:
If you do not see the Web UI Setup form then something went wrong. It would be a good idea to re-deploy with APP_DEBUG set to 1 and then you will get an error message in the web interface. It is also good to read the text that appears in the CLI after you ran
Common issues are:
- Database password not matching in the compose file and the environment file.
- The APP_KEY string not being long enough.
You should now have your own open source invoice solution. In future I will show how to get SSL enabled.
First published: 16th August 2018