Libki / libki-server

Libki Server
Other
55 stars 28 forks source link

Getting started using Docker #354

Open joeskeen opened 3 months ago

joeskeen commented 3 months ago

I just discovered Libki and I'm excited to use it! When evaluating new software, I like to do so in a Docker environment to make it easier to repeat deployment once I decide to move forward with it.

The documentation says you can use the official Docker image to get started with Libki, but there isn't much additional information about what else needs to be done. I think I may have figured it out, but I thought I'd report what I've done here to see if I'm on the right track. If I am, perhaps we can update the docs with some additional instructions.

To Reproduce

In a clean environment, run docker run libki/libki-server:latest (environment variables omitted here for brevity)

Some observations:

My solution

I think it would be cool if we could point new users to a sample docker-compose.yml file that allows them to try out Libki very easily. This is the file I came up with, which exposes the port, sets up cron, initializes the admin user, and runs Libki Server. It also makes sure that the db is up and running before starting the server. All sensitive data (credentials) are read from a .env file which exists as a sibling to the docker-compose.yml.

I would welcome any feedback or suggestions.

version: "3.7"

#############################################
# Instructions:
# 
# create a .env file in the same directory as this file with the following content:
#
# LIBKI_ADMIN_USERNAME=your_admin_username
# LIBKI_ADMIN_PASSWORD=your_admin_password
# DB_NAME=your_db_name
# DB_USER=your_db_user
# DB_PASS=your_db_pass
# DB_ROOT_PASS=your_db_root_pass
# 
# then run the following command:
# 
# docker compose up -d
# (you can remove '-d' to debug output interactively)
#############################################

services:
  libki:
    restart: always
    build:
      context: .
      dockerfile_inline: |
        FROM libki/libki-server:latest

        # set up cronjobs; see https://manual.libki.org/master/libki-manual.html#_cronjobs
        RUN install_packages cron
        RUN (crontab -l ; echo "* * * * * /app/script/cronjobs/libki.pl") | crontab -
        RUN (crontab -l ; echo "0 0 * * * /app/script/cronjobs/libki_nightly.pl") | crontab -
        RUN update-rc.d cron defaults

        EXPOSE 3000

        # capture env, initialize db, ensure admin user credentials are up-to-date, then start the server
        # environment variables passed in from Docker get persisted at the top of the crontab file so all cron jobs have access to them
        CMD (set | grep LIBKI ; crontab -l) | crontab - \
            && ./installer/update_db.pl \
            && /app/script/administration/create_user.pl -u ${LIBKI_ADMIN_USERNAME} -p ${LIBKI_ADMIN_PASSWORD} -s \
            && service cron start \
            && plackup -s Gazelle --port 3000 --max-reqs-per-child 50000 --max-workers ${LIBKI_MAX_WORKERS} -E production -a /app/libki.psgi
    environment: # see https://manual.libki.org/master/libki-manual.html#_docker
      - LIBKI_INSTANCE=
      - LIBKI_DB_DSN=dbi:mysql:${DB_NAME};host=db;port=3306
      - LIBKI_DB_USER=${DB_USER}
      - LIBKI_DB_PASSWORD=${DB_PASS}
      - LIBKI_DB_HOST=db
      - LIBKI_DB_PORT=3306
      - LIBKI_DB_DATABASE=${DB_NAME}
      - LIBKI_TZ=America/Denver
    ports: # change the first port (left of the ':') below to the port you want to use on the host to access Libki Server
      - "3000:3000"
    depends_on:
      db:
        condition: service_healthy
        restart: true

  db:
    image: mysql:5.7
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASS}
      - MYSQL_DATABASE=${DB_NAME}
      - MYSQL_USER=${DB_USER}
      - MYSQL_PASSWORD=${DB_PASS}
    volumes:
      - ./libki_db:/var/lib/mysql
    ports:
      - "3306:3306" # you can remove this if you don't need to access MySQL directly from the host; the libki container will still be able to access it
    healthcheck: # wait for MySQL to be ready before starting Libki
      test: mysqladmin ping -h 127.0.0.1 -u $$MYSQL_USER --password=$$MYSQL_PASSWORD
      start_period: 5s
      interval: 5s
      timeout: 5s
      retries: 55

EDIT: I've tweaked it so Cron runs properly. The main thing with the Cron jobs is that it needs to have access to the environment variables passed in via Docker.

kylemhall commented 3 months ago

This looks great! Are you able to make a pull request that updates the existing docker/docker-compose.yml? My only suggestion would be to use a named volume of the database data. My compose file is using mariadb but I don't have any strong feelings about maria vs mysql at this time.

joeskeen commented 3 months ago

Will do :+1: