Bookstack Using Docker Compose

Creating a Bookstack on localhost

A local Bookstack can be ran easily with docker using the default localhost settings. To install docker, follow the Docker Installation Instructions and create a docker-compose.yml configuration that matches the format on the Linuxserver.io Repository (DockerHub Image) page. If you've never used Docker before, it's a good idea to check out Play With Docker - a community project sponsored by Docker.

Creating a docker-compose.yml

Docker Compose utilizes a docker-compose.yml file to organize and configure the services running on a host using Docker. The docker-compose.yml should look something like the following, grabbed directly from the Linuxserver.io GitHub Repository for the Docker image we are using below - linuxserver/bookstack.

version: "2"
services:
  bookstack:
    image: linuxserver/bookstack
    container_name: bookstack
    environment:
      - PUID=1000
      - PGID=1000
      - DB_HOST=bookstack_db
      - DB_USER=bookstack
      - DB_PASS=<yourdbpass>
      - DB_DATABASE=bookstackapp
    volumes:
      - <path to data>:/config
    ports:
      - 6875:80
    restart: unless-stopped
    depends_on:
      - bookstack_db
  bookstack_db:
    image: linuxserver/mariadb
    container_name: bookstack_db
    environment:
      - PUID=1000
      - PGID=1000
      - MYSQL_ROOT_PASSWORD=<yourdbpass>
      - TZ=Europe/London
      - MYSQL_DATABASE=bookstackapp
      - MYSQL_USER=bookstack
      - MYSQL_PASSWORD=<yourdbpass>
    volumes:
      - <path to data>:/config
    restart: unless-stopped

Be sure to edit this file to change the passwords above before spinning up your container, and pay attention to the <path to data> within the docker-compose volumes. This should be the path to the data directory which will hold the mounted volumes shared between the Docker Container and its host. If you are running a strict firewall or set of iptables, be sure to adjust them accordingly to the ports within the docker-compose.yml.

If you are just spinning up a local container, and you are able to view the local page hosted by the container, you shouldn't need to worry about firewall rules since all the traffic will be internal.

Defining Our Services

This file basically has a few basic statements that we should understand before continuing, I'll leave the rest to the Docker Documentation.

To start, I added some comments to our default configuration, see them below for some explanation on the settings -

version: "2"
services:

# Define our bookstack service name
  bookstack:

    # Specify Image to be used in the bookstack container, and name it.
    image: linuxserver/bookstack
    container_name: bookstack

    # Define environment variables to pass to the container
    # This is the 'configuration' of your service as a container and is specific to the Docker Image
    environment:
      ...
      # If you don't know what some environment variables are, check Docker Hub page for the Image
      ...
    # Define volumes, if any
    # This is useful for syncronizing data between the container and the host for easy access to files or directories
    volumes:
      # General format to bind the local .../host directory to the .../container directory-
      # - /path/on/host:/path/on/container
      - <path to data>:/config

    # Ports to use for our service, check these are reflected in your firewall and iptables
    ports:
      - 6875:80

    # If the container crashes, what should Docker do?
    restart: unless-stopped

    # Does this service depend on another service?
    depends_on:
      - bookstack_db

  # The following configuration for our database container should look familiar now..
  # Notice that if the setting isn't used below within the service or its containers, it can simply be removed.
  bookstack_db:
    image: linuxserver/mariadb
    container_name: bookstack_db
    environment:
# Check Docker Hub to get environment settings for your image...
    volumes:
      - <path to data>:/config
    restart: unless-stopped

We begin our docker-compose.yml file by specifying the version of docker-compose we are using, and creates the block in which we will define our services, in this case we are creating two services, each hosting one Docker Image within a container - linuxserver/bookstack and linuxserver/mariadb. We need the Bookstack database (bookstack_db service defined above) to be active for our Bookstack application to work properly, so we defined the depends_on variable for docker-compose within the bookstack service itself.

Starting Our Containers

Now, all we need to do is store this docker-compose.yml file within a directory we wish to admin the container from, and run docker-compose up -d to start our services that we have defined. the -d flag simply tells docker-compose that we wish the detatch the processes from our current terminal session, which prevents us from inheriting the active logs from the services we started. If you want to see these logs as an active feed after you spin up your services, simply run docker-compose logs -f to do so.

That's it! As long as you have no custom domain configuration and only plan to view this Bookstack instance locally, there is no other configuration to be done on the back end of your test-wiki. You should be able to open your web browser and visit localhost:8080 to see your Bookstack application.

Run docker ps to see a list of containers, and the ports they are running on. This helps to debug network issues when attempting to view our application. If localhost:8080 does not work, check that your output is appropriate for the use of that port.

In the case of this Bookstack instance, we are using https to encrypt the web traffic, which runs over port 443/tcp. So when you visit knoats.com in your web browser, I have done some DNS / NGINX configuration in place to ensure that all traffic is routed through the port 443, which passes this encrypted traffic to my host where it is decrypted and passed internally from the local port 0.0.0.0:6875/tcp to our containerized port 80/tcp which serves our web content using NGINX. In this case, our web content is Bookstack, but technically - this could be any web content you wanted to put in this directory. If you did want to host something else, you should always adjust the Docker Images you are using appropriately.

CONTAINER ID        IMAGE                   COMMAND             CREATED             STATUS              PORTS                           NAMES
xxxxxxxxxxxx        linuxserver/bookstack   "/init"             25 hours ago        Up 25 hours         443/tcp, 0.0.0.0:6875->80/tcp   bookstack
xxxxxxxxxxxx        linuxserver/mariadb     "/init"             26 hours ago        Up 25 hours         3306/tcp                        bookstack_db

Some of this information has been changed for security reasons - such as ports and the CONTAINER ID's seen above. If you want to configure SSL for your bookstack, see Knoats - NGINX SSL Configuration