Docker

Note very loudly that additional Docker options should be set in the env file, and they require a full container rebuild!

❗️

NOTICE:

The ONLY docker image we support is snipe/snipe-it. If you grabbed a docker image from any other repo, you're kinda on your own, since we cannot be responsible for images we do not manage directly.

Docker is a very popular software containerization platform. While it's not difficult to use, it can be a little confusing for folks who are less familiar with containerization.

We'll attempt to walk you through a Docker setup here, but please see the Docker documentation for a more in-depth understanding of Docker fundamentals. If you don't know the implications of the steps you're taking here, you could potentially lose access to your data.

🚧

A NOTE FOR N00BS:

This Docker image uses some advanced concepts such as linking, storage volumes, and multiple images, so it may not be a good choice for learning Docker, however if you're willing to put some time into researching the concepts and background of Docker, we'll be happy to help you as best we can.

🚧

Any configuration changes in your docker-env file will require a container restart!

If you don't recreate your Snipe-IT container, it won't pick up the new values. That's not a Snipe-IT thing, that's a docker thing.

The easiest way to get started with Snipe-IT on Docker is to use the Docker image we push to Docker Hub:

docker pull snipe/snipe-it

If you'd rather grab a specific version of Snipe-IT, use the tag for the release you'd like to use. For example, to use the 5.1.7 release, you would use:

docker pull snipe/snipe-it:v5.1.7

For a list of all available Docker version tags, check out the tags page on Dockerhub.

How to Get Up and Running

🚧

Options Have Changed From v2.x!

Please note some of the options have changed, and some new options are now required!

Docker's Environment Variables

Snipe-IT's Docker configuration requires many different environment variables in order to function correctly. To keep things simple, we try to centralize all of those settings in an environment file. If you are using a method other than the standard docker CLI to integrate Snipe-IT into your docker environment, then you will need to make sure to pass all of the below mentioned variables into your Snipe-IT environment.

The Snipe-IT env-file is a simple text file with some variables and values that your Snipe-IT installation needs, separated by = signs. These environment variables will also affect your MySQL configuration.

You can call this file anything you want, and put it wherever you like, just remember what you called it and where you put it, since you'll need to reference this file when you run your Docker containers, using the --env-file=<your_docker_env_file_name> argument. You'll see examples of this in the commands further down the page as you initialize your Docker container.

For the purposes of this documentation, we'll call our file my_env_file.

Your my_env_file is not the same .env file Snipe-IT uses directly, but the values you put in it are used to generate the .env file that Snipe-IT does use, so what you put in here matters.

❗️

Any Other .env Options You want to Set Should Be Set Here!

Any additional parameters you set in your my_env_file will be automatically propagated into your running Snipe-IT environment.

So just because we don't list every single possible .env variable in the my_env_file doesn't mean we don't support it - please set the option in your my_env_file and launch a new container to pick up your latest changes!

Your my_env_file should look like this:

# Mysql Parameters
MYSQL_ROOT_PASSWORD=YOUR_SUPER_SECRET_PASSWORD
MYSQL_DATABASE=snipeit
MYSQL_USER=snipeit
MYSQL_PASSWORD=YOUR_snipeit_USER_PASSWORD

# Email Parameters
# - the hostname/IP address of your mailserver
MAIL_PORT_587_TCP_ADDR=smtp.whatever.com
#the port for the mailserver (probably 587, could be another)
MAIL_PORT_587_TCP_PORT=587
# the default from address, and from name for emails
[email protected]
MAIL_ENV_FROM_NAME=Your Full Email Name
# - pick 'tls' for SMTP-over-SSL, 'tcp' for unencrypted
MAIL_ENV_ENCRYPTION=tcp
# SMTP username and password
MAIL_ENV_USERNAME=your_email_username
MAIL_ENV_PASSWORD=your_email_password

# Snipe-IT Settings
APP_ENV=production
APP_DEBUG=false
APP_KEY=<<Fill in Later!>>
APP_URL=http://127.0.0.1:<<YOUR_PORT_NUMBER>>
APP_TIMEZONE=US/Pacific
APP_LOCALE=en
  
# Docker-specific variables
PHP_UPLOAD_LIMIT=100

Remember, if you're not using an .env-file, you will have to pass all of these variables into your docker container when you launch it.

First get a MySQL container running. MySQL 5.6 or earlier are easiest.

docker run --name snipe-mysql --env-file=my_env_file --mount source=snipesql-vol,target=/var/lib/mysql -d -P mysql:5.6

If your my_env_file contains a MYSQL_USER, MYSQL_PASSWORD, and a MYSQL_DATABASE, then the MySQL container will automatically create that database and grant permissions to access it. If you're using an external database, or an already existing container, you'll have to create a database for Snipe-IT to use, and grant a user access to it - and put those credentials in your my_env_file.

The data for your MySQL container will live in the named volume snipesql-vol. Docker will create this volume for you if it does not exist already.

🚧

WARNING:

Newer MySQL containers (5.7 and later, or MariaDB) may run in strict-mode by default, and the initial migrations and application setup will fail in strict mode. If you want to use one of those versions, you need to disable strict mode first!

That should set you up with your database to use. (You can also specify environment variables on the command-line instead of the env-file, but that can get very clunky very quickly; see docker run --help for details)

Using a Standalone Database (not a container)

If you're using a separate, standalone database, you can specify the hostname as MYSQL_PORT_3306_TCP_ADDR. If your database runs on a different port, you can specify that with MYSQL_PORT_3306_TCP_PORT. You don't need to specify the MYSQL_ROOT_PASSWORD.

Thus, your config should look as follows:

# Mysql Parameters
MYSQL_PORT_3306_TCP_ADDR=XXX.XXX.XXX.XXX
MYSQL_PORT_3306_TCP_PORT=3306

MYSQL_DATABASE=snipe_it
MYSQL_USER=snipe_it_db_user
MYSQL_PASSWORD=snipe_it_db_user_password

📘

NOTE:

If your Email solution requires its own container, start that container or service. Make sure to expose port 587 for mail submission, and use --link mail:....

Start your Snipe-IT container

First, we'll need to generate an app key. If you already have a Snipe-IT container running, make note of the APP_KEY. In older versions of Snipe-IT, it was stored in app/config/production/app.php.

Otherwise, you can easily generate a new one, just run the container:

docker run --rm snipe/snipe-it

Or to run with your specified version:

docker run --rm snipe/snipe-it:v4.1.13

The output should look like:

Please re-run this container with an environment variable $APP_KEY
An example APP_KEY you could use is: 
base64:D5oGA+zhFSVA3VwuoZoQ21RAcwBtJv/RGiqOcZ7BUvI=

Add that APP_KEY to your docker env-file (we left a placeholder for it in your starting docker env file, above). Make sure to include the base64: prefix if it is given! If you're not using an env-file, you will need to pass the APP_KEY as an environment variable to your docker container.

You'll also need to decide which port number to 'expose' for the HTTP and HTTPS endpoints. Once you've selected one, make sure to set your APP_URL variable in your Docker env-file to reference it.

Finally, decide whether or not you want to have your Snipe-IT container manage SSL for you, or not.

As a side-note, if you're running boot2docker or docker-machine, you may need to prefix the port declarations below with an IP address - $(docker-machine ip default): or 123.45.78.89:

SSL disabled

Start your Snipe-IT container:

If you pulled the image with exact version number tag than you need apply here as well of course.

Start with the latest version:

docker run -d -p YOUR_PORT_NUMBER:80 --name="snipeit" --link snipe-mysql:mysql --env-file=my_env_file --mount source=snipe-vol,dst=/var/lib/snipeit snipe/snipe-it

The 'named volume' snipe-vol will be created if it does not already exist.

Version specific start:

docker run -d -p YOUR_PORT_NUMBER:80 --name="snipeit" --link snipe-mysql:mysql --env-file=my_env_file --mount source=snipe-vol,dst=/var/lib/snipeit snipe/snipe-it:v.4.1.13

SSL enabled

Start your Snipe-IT container - but be prepared to copy your SSL key and certificate to your storage volume. When you first launch the Snipe-IT container, the named volume snipe-vol will be created and initialized. You can use the docker cp command to copy your certificate data to the storage volume, at /var/lib/snipeit/ssl/snipeit-ssl.crt and /var/lib/snipeit/ssl/snipeit-ssl.key.

docker run -d -p YOUR_PORT_NUMBER:80 -p YOUR_SSL_PORT:443 --name="snipeit" --link snipe-mysql:mysql --mount source=snipe-vol,dst=/var/lib/snipeit --env-file=my_env_file snipe/snipe-it

Version specific start with SSL

docker run -d -p YOUR_PORT_NUMBER:80 -p YOUR_SSL_PORT:443 --name="snipeit" --link snipe-mysql:mysql --mount source=snipe-vol,dst=/var/lib/snipeit --env-file=my_env_file snipe/snipe-it:v4.1.13

Email, Management, Access

If you have a separate container running for email, you will also want a --link setting for email as well.

That's It!

You can now initialize the application and database by pointing your web browser to: http://your_ip:YOUR_PORT, which will automatically redirect you to the setup screen.

Updating Snipe-IT or MySQL

To upgrade your Snipe-IT installation, you should stop your old container, re-pull the latest Snipe-IT version, then launch the new container as before, but connecting to the same storage volume - named snipe-vol in our examples. You will have to rename your old container to be able to reuse the 'snipeit' name.

After that, you may need to run migrations using docker run snipeit php artisan migrate.

Once you're completely sure that everything on your new installation is working, you may delete the old Snipe-IT container.

To upgrade MySQL, stop your old container, pull whatever new version you want to switch to, and make sure to run your new container with the same named volume - we called it snipesql-vol in our examples.

Hosting Snipe-IT and MySQL on Azure

Azure Web Apps can host Docker containers, using Azure Storage for their instance data, and MySQL is available as managed service on Azure. So Azure can be used to host a private instance of Snipe-IT

Create an Azure MySQL PaaS instance

  1. In the Azure Portal, create a new 'Azure Database for MySQL flexible server' resource in a new resource group
    • Provide a name for the instance
    • Set your region
    • Workload Type - can use the lowest 'for development or hobby projects'
    • Set the MySQL username and password
    • For networking pick 'allow public access' and 'allow public access for any Azure service'

      You can add your Client IP address to the firewall rules if you want to be able to connect to the DB from your local machine, but this is not essential. I had enabled this to do some testing with a locally hosted Docker instance.

  2. When the instance is created open it in the Azure Portal
    • Go to the Networking tab and download the SSL certificate DigiCertGlobalRootCA.crt.pem (you need it later)
    • Go to the Database tab and create a new empty DB snipe-it with default settings.

Create an Azure Storage Account

  1. Open the Azure Portal, create a new 'Storage Account' in same resource group as used for the MySQL
    • Provide a name for the instance
    • Set your region
    • For networking pick 'allow public access'
  2. When the resource is created open it in the Azure Portal
  3. In storage explorer create a new File Share called snipeit
  4. Upload the SSL Cert DigiCertGlobalRootCA.crt.pem to this share
  5. In storage explorer create a new File Share called snipeit-logs

Create an Azure Web App

  1. Open the Azure Portal, create a new 'Web App' in same resource group as used for the MySQL

    • Provide a name for the instance
    • Pick the publish type to be Docker Container
    • Set your region
    • Create a pricing tier, Linux Basic B1 can be used
    • For Docker settings picked the follow (though we override these later with a compose file)
      • Single Container
      • Docker Hub
      • With the image name snipe/snipe-it:latest (or can pick a specific version)
  2. When the resource is created open it in the Azure Portal

  3. In the configuration Path Mappings add a new Azure Storage Mount for the cert and other local storage

    • Name - snipeit
    • Mount Path - /var/lib/snipeit
    • Type - Azure Files using the previously created file share
  4. In the configuration Path Mappings add a new Azure Storage Mount for the logs

    • Name - snipeit-logs
    • Mount Path - /var/www/html/storage/logs
    • Type - Azure Files using the previously created file share
  5. In the configuration Application Settings I added the following new Application Settings

    • MYSQL_DATABASE - snipeit matching the MySQL DB name
    • MYSQL_USER to the username for the MySQL instance
    • MYSQL_PASSWORD to the password for the MySQL instance
    • DB_CONNECTION to mysql
    • MYSQL_PORT_3306_TCP_ADDR to the name of the MySQL instance <my-instance>.mysql.database.azure.com
    • MYSQL_PORT_3306_TCP_PORT to 3306
    • DB_SSL_IS_PAAS to true
    • DB_SSL to true
    • DB_SSL_CA_PATH to /var/lib/snipeit/DigiCertGlobalRootCA.crt.pem matching the path to the SSL cert
    • APP_URL to the URL of the Web App https://<my-instance>.azurewebsites.net
    • APP_KEY to a unique ID in the form base64:6M3RwWh4re1FQGMTent3hON9D7ZJJDHxW1123456789=. If you don't set this and start the container, whilst watching the log stream, you will see the new key generated which you can use
    • MAIL_DRIVER to smtp
    • MAIL_ENV_ENCRYPTION to tcp
    • MAIL_PORT_587_TCP_ADDR to smtp.sendgrid.net
    • MAIL_PORT_587_TCP_PORT to 587
    • MAIL_ENV_USERNAME to apikey
    • MAIL_ENV_PASSWORD your SendGrid API Key
    • MAIL_ENV_FROM_ADDR to the email SNipe IT notifications should come from
    • MAIL_ENV_FROM_NAME to Snipe IT or whatever you want the email to be from
    • You can also set the APP_DEBUG to true or false. If true this means more detailed error messages are shown in the Snipe-IT UI that do not appear in the log stream
  6. In the deployment center pick Docker Compose and provided the follow config to mount the storage

    version: "3"
    
    services:
    snipe-it:
        image: snipe/snipe-it:latest
        volumes:
        - snipeit:/var/lib/snipeit
        - snipeit-logs:/var/www/html/storage/logs
    
    volumes:
    snipeit:
        external: true
    snipeit-logs:
        external: true
    
  7. Restart your Web App

  8. And that should be it, the container should start and you should be able to access the Snipe-IT UI based setup Wizard via the URL of the Web App, as per the standard configuration process for Snipe-IT

Comments & Tips

MySQL SSL Certificate not found

If the MySQL SLL Certificate cannot be found for any reason, such as an incorrect path or missing volume mount, you get the same error message in the Snipe-IT UI

SQLSTATE[HY000] [2002]  (trying to connect via (null)) (SQL: select * from information_schema.tables where table_schema = snipeit and table_name = migrations and table_type = 'BASE TABLE')

There was nothing more useful in the Web App Log Stream (the container output). The best option is to set the ENV setting APP_DEBUG to true. After which more useful error messages can be seen in the UI logs

MySQL Initial Migration Failing

If you get the following error in the UI when the container is trying to create the DB Tables

SQLSTATE[42000] Syntax error or access violation 1068 Multiple primary key defined

It is because the MySQL instance has incorrect server parameters set. The fix was to set the following three MySQL Server Parameters, in MySQL instance via the Azure Portal, to OFF

  • innodb_buffer_pool_load_at_startup
  • innodb_buffer_pool_dump_at_shutdown
  • sql_generate_invisible_primary_key

I have no idea why my first Azure MySQL instance had these values set to OFF and my other instances had them set to on ON. I guess I am lucky at least one was set to OFF so I could work out what was wrong.

ADVANCED docker usage

❗️

WARNING! Advanced users ONLY!

These are all advanced features of Docker. Please only use them if you are already extremely knowledgeable about how to use Docker.

Bind Mounts

Instead of using named volumes, as above, you may instead use a 'bind mount' to point to a local directory. This was an older method that Snipe-IT's docker integration used, but Docker no longer recommends it.

If you need that feature for whatever reason, you should pass the fully-qualified path (absolute path) instead of the named volume in the various above commands.

Specifically, the mount parameter in your command-lines should look something like this:

--mount source=/full/path/to/your/snipe-directory/,dst=/var/lib/snipeit

You may need to create various folders in that directory. See the Dockerfile and the /entrypoint.sh files for specific details.

Behind a SSL / HSTS reverse proxy

If your container is setup behind a trusted reverse proxy (such as nginx) and HSTS is active, you'll need to pass a few more parameters for Snipe-It to work. Add to your .env file at least the following lines:

APP_TRUSTED_PROXIES=REMOTE_ADDR
SECURE_COOKIES=true

For Development

You can build the snipe-it image using the Dockerfile at the root directory of Snipe-IT by doing this:

docker build -t snipe-it .

Then you can use your newly built image as snipe-it

When you call docker run - make sure to mount your own snipe-it directory over the /var/www/html directory. Something like:

docker run -d -v /Path/To/My/snipe-it/checkout:/var/www/html -P --name="snipeit" --link mysql:mysql snipeit

Then your local changes to the code will be reflected. You will have to re-run composer install -

docker exec -i -t snipeit composer install

And you may still need to generate the key with -

docker exec -i -t snipeit php artisan key:generate --env=production

While you're developing, you may need to occasionally run:

docker exec snipeit composer dump

To fix the autoloading cache (if, for example, your class names change, or you add new ones...)