Baïkal is a quite popular Calendar+Contacts server. It supports CalDAV as well as CardDAV.

I’ve been using it for my calendars and adressbooks already for more than 4 years now. However, I initially installed it as plain PHP application with a MySQL database. The developers also announced quite early, that they are working on a Docker image, but there is nothing useful as of mid 2018. So far they just provide a quite inconvenient how-to and a list of issues that apparently prevent them from providing a proper Docker image. Thus, I just dockerised the application myself :)

The Docker image

Actually, creating a Docker image for Baïkal was super easy. In the end, it is “only” a PHP application ;-) The corresponding Dockerfile can be found in the root directory of Baïkal’s git repository (at least in my fork). The latest version at the time of writing is:

FROM php:apache
MAINTAINER martin scharm <>

# we're working from /var/www, not /var/www/html
# the html directory will come with baikal
WORKDIR /var/www

# install tools necessary for the setup
RUN apt-get update \
 && apt-get install -y -q --no-install-recommends \
    unzip \
    git \
    libjpeg62-turbo \
    libjpeg62-turbo-dev \
    libpng-dev \
    libfreetype6-dev \
    ssmtp \
 && apt-get clean \
 && rm -r /var/lib/apt/lists/* \
 && a2enmod expires headers

# for mail configuration see

# install php db extensions
RUN docker-php-source extract \
 && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
 && docker-php-ext-install -j$(nproc) pdo pdo_mysql \
 && docker-php-source delete

# install composer
RUN php -r "copy('', 'composer-setup.php');" \
 && php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
 && mkdir -p composer/packages \
 && php composer-setup.php --install-dir=composer \
 && php -r "unlink('composer-setup.php');" \
 && chown -R www-data: composer

# prepare destination
RUN rm -rf /var/www/html && chown www-data /var/www/
ADD composer.json /var/www/
ADD Core html /var/www/Core/
ADD html /var/www/html/

# install dependencies etc
USER www-data
RUN composer/composer.phar install

USER root

# the Specific dir is supposed to come from some persistent storage
VOLUME /var/www/Specific

So, it basically

  • installs some dependencies through apt-get,
  • installs the PDO-MySQL extension,
  • installs composer,
  • adds the Baikal sources into the image,
  • and finally installs remaining Baikal dependencies through composer.

I distribute the image as binfalse/baikal.

Using the Docker image

Using the image is fairly simple. Basically, you only need to mount some persistent space to /var/www/Specific

docker run -it --rm -p 80:80 -v /path/to/persistent:/var/www/Specific binfalse/baikal

To start with, you can use the original Specific directory from the Baïkal repository. Then head to your Baikal instance (which will probably redirect to BASEURL/admin/install), and setup your server. Every configuration will be stored in the mounted volume at /path/to/persistent.


To support encrypted connections you would need to mount the certificates as well as a modified Apache configuration into the container. However, I recommend to run it behind a reverse proxy, such as binfalse/nginx-proxy, and let the proxy handle all SSL connections (as for all other containers). This way, you just need one proper SSL configuration.


The default SQLite database is perfect for a first test, but is slow and just allows for a limited amount of SQL variables. If you for example have more than 999 contacts, the first sync of a clean WebDAV device will result in an exception such as:

PDOException: SQLSTATE[HY000]: General error: 1 too many SQL variables

Thus, for production you may want to switch to a proper database, such as MariaDB. Lucky you, the Docker image supports MySQL! ;-)

To reproducibly assemble both containers, I recommend Docker-Compose. Here is a sample config with two containers baikal and baikal-db:

version: '2'
        restart: always
        image: binfalse/baikal
        container_name: baikal
            - /srv/baikal/config:/var/www/Specific
            - baikal-db
        restart: always
        image: mariadb
        container_name: baikal-db
            - /srv/baikal/database:/var/lib/mysql
            MYSQL_ROOT_PASSWORD: roots-difficult-password
            MYSQL_DATABASE: baikal
            MYSQL_USER: baikal
            MYSQL_PASSWORD: baikals-difficult-password

This assumes, that your Baikal configuration can be found in /srv/baikal/config. The database will be stored in /srv/baikal/database. Also note the database credentials for configuring Baikal. If you’re not running a reverse proxy in front of the application, you also need to add some port forwarding for the baikal container:

version: '2'
        restart: always
        image: binfalse/baikal
            - "80:80"
            - "443:443"

Mail support

I’m not sure why, but Baikal’s list of issues included support for mail. However, adding mail support should also be fairly easy if needed. I already wrote a How-To for PHP-mail in Docker.

Martin Scharm

stuff. just for the records.

Post a comment

read more about submitting comments