Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
*

# Allow specific files
!/apache.conf
!/apache/*
!/php.ini
!/koel-entrypoint
!/koel-init
5 changes: 1 addition & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
# Contains DB passwords
.env.dev
# Contains Koel APP_KEY
.env.koel
.env*
# Cache for direnv
.direnv/
.envrc
Expand Down
195 changes: 134 additions & 61 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,15 +1,66 @@
# The runtime image.
FROM php:8.4.8-apache-bookworm

FROM alpine:3.22.1
# The koel version to download
ARG KOEL_VERSION_REF=v7.12.0

# Install vim for easier editing/debugging
RUN apt-get update && apt-get install -y vim
RUN apk add --no-cache --no-interactive \
curl \
apache2 \
apache2-proxy \
# php-fpm because it's so much faster and efficient in handling web requests, php for cli commands. need to find a way to maybe not have both bloating the image
php \
php-fpm \
libzip-dev \
zip \
ffmpeg \
libpng-dev \
libjpeg-turbo-dev \
libpq-dev \
libwebp-dev \
libavif-dev \
# https://laravel.com/docs/8.x/deployment#server-requirements
php83-ctype \
php83-fileinfo \
php83-json \
php83-mbstring \
php83-openssl \
php83-tokenizer \
php83-xml \
php83-dom \
php83-bcmath \
php83-exif \
php83-gd \
php83-pdo \
php83-pdo_mysql \
php83-pdo_pgsql \
php83-pgsql \
php83-zip \
php83-session \
busybox-suid \
musl-locales \
musl-locales-lang \
tzdata \
# as well as nano for easier debugging and updating configs
nano \
ncdu \
# Set locale to prevent removal of non-ASCII path characters when transcoding with ffmpeg. do this first so all the php configurations make use of this as well
# See https://github.com/koel/docker/pull/91 & https://krython.com/post/resolving-alpine-linux-locale-issues/
&& echo "en_US.UTF-8 UTF-8" > /etc/locale.gen \
&& export LANG=en_US.UTF-8 \
&& export LC_ALL=en_US.UTF-8 \
&& echo 'export LANG=en_US.UTF-8' >> /etc/profile \
&& echo 'export LC_ALL=en_US.UTF-8' >> /etc/profile


# Download the koel release matching the version and remove anything not necessary for production

RUN adduser -S www-data -G www-data -h /var/www/ -H
RUN mkdir -p /var/www/html && chown www-data:www-data /var/www/html
USER www-data

# Download koel and put the files in the right places
RUN curl -L https://github.com/koel/koel/releases/download/${KOEL_VERSION_REF}/koel-${KOEL_VERSION_REF}.tar.gz | tar -xz -C /tmp \
&& cd /tmp/koel/ \
# Cleanup the junk from the tar, probably should rework the build at some point to not exclude things not useful outside of dev at that layer already
&& rm -rf .editorconfig \
.eslintignore \
.eslintrc \
Expand All @@ -31,86 +82,108 @@ RUN curl -L https://github.com/koel/koel/releases/download/${KOEL_VERSION_REF}/k
ruleset.xml \
scripts/ \
tag.sh \
vite.config.js

# Install koel runtime dependencies.
RUN apt-get update \
&& apt-get install --yes --no-install-recommends \
cron \
libapache2-mod-xsendfile \
libzip-dev \
zip \
ffmpeg \
locales \
libpng-dev \
libjpeg62-turbo-dev \
libpq-dev \
libwebp-dev \
libavif-dev \
&& docker-php-ext-configure gd --with-jpeg --with-webp --with-avif \
# https://laravel.com/docs/8.x/deployment#server-requirements
# ctype, fileinfo, json, mbstring, openssl, tokenizer and xml are already activated in the base image
&& docker-php-ext-install \
bcmath \
exif \
gd \
pdo \
pdo_mysql \
pdo_pgsql \
pgsql \
zip \
&& apt-get clean \
# Create the music volume so it has the correct permissions
&& mkdir /music \
&& chown www-data:www-data /music \
vite.config.js \
tests/songs \
pnpm-lock.yaml \
.husky \
README.md \
CODE_OF_CONDUCT.md \
.vscode \
tailwind.config.js \
eslint.config.js \
postcss.config.cjs \
commitling.config.js \
.htaccess.example \
&& cp -R /tmp/koel/. /var/www/html \
# we use php-pfm because it's plain better, but that means htaccess php directives can't be parsed here
&& sed -e '/^php*/ s/^#*/#/' -i /var/www/html/public/.htaccess \
# Create the search-indexes volume so it has the correct permissions
&& mkdir -p /var/www/html/storage/search-indexes \
&& chown www-data:www-data /var/www/html/storage/search-indexes \
# Set locale to prevent removal of non-ASCII path characters when transcoding with ffmpeg
# See https://github.com/koel/docker/pull/91
&& echo "en_US.UTF-8 UTF-8" > /etc/locale.gen \
&& /usr/sbin/locale-gen

# Copy Apache configuration
COPY ./apache.conf /etc/apache2/sites-available/000-default.conf
&& [ ! -f /var/www/html/public/manifest.json ] && cp /var/www/html/public/manifest.json.example /var/www/html/public/manifest.json || true \
&& chown -R www-data:www-data /var/www/html \
# Cleanup the temp download
&& rm -rf /tmp/*

# Copy php.ini
COPY ./php.ini "$PHP_INI_DIR/php.ini"
# /usr/local/etc/php/php.ini

# Deploy Apache configuration
RUN a2enmod rewrite
# Install x-sendfile for apache2, fix home folder
USER root
RUN apk add --no-cache apache2-dev gcc musl-dev \
&& curl -o mod_xsendfile.c https://tn123.org/mod_xsendfile/mod_xsendfile.c \
&& apxs -cia mod_xsendfile.c \
&& rm mod_xsendfile.* \
&& apk del --no-cache apache2-dev gcc musl-dev \
&& mkdir /var/www/lib \
&& ln -s /usr/lib/apache2 /var/www/lib/apache2

# Copy the downloaded release
RUN cp -R /tmp/koel/. /var/www/html
RUN [ ! -f /var/www/html/public/manifest.json ] && cp /var/www/html/public/manifest.json.example /var/www/html/public/manifest.json || true
RUN chown -R www-data:www-data /var/www/html

# Create /tmp/koel if it doesn't exist, and set ownership to www-data
# Create /tmp/koel
RUN mkdir -p /tmp/koel \
&& chown www-data:www-data /tmp/koel \
&& chmod 755 /tmp/koel
&& chown www-data:www-data /tmp/koel \
&& chmod 755 /tmp/koel\
# Create the music volume so
&& mkdir /music \
&& chown www-data:www-data /music \
&& mkdir -p /cache/img/artists \
&& mkdir -p /cache/img/avatars \
&& mkdir -p /cache/img/covers \
&& mkdir -p /cache/img/playlists \
&& mkdir -p /cache/img/radio-stations \
&& chown -R www-data:www-data /cache \
&& chmod -R 755 /cache \
# redirect public img storage into the cache, putting this here and not with the other koel file setups because it makes more sense here, and they are empty folder so don't have a significant impact on file size
&& rm -r /var/www/html/public/img/artists \
&& rm -r /var/www/html/public/img/avatars \
&& rm -r /var/www/html/public/img/covers \
&& rm -r /var/www/html/public/img/playlists \
&& ln -s /cache/img/artists /var/www/html/public/img/artists \
&& ln -s /cache/img/avatars /var/www/html/public/img/avatars \
&& ln -s /cache/img/covers /var/www/html/public/img/covers \
&& ln -s /cache/img/playlists /var/www/html/public/img/playlists \
&& ln -s /cache/img/radio-stations /var/www/html/public/img/radio-stations

# Volumes for the music files and search index
# Volumes for the music files, search index and image cache
# This declaration must be AFTER creating the folders and setting their permissions
# and AFTER changing to non-root user.
# Otherwise, they are owned by root and the user cannot write to them.
VOLUME ["/music", "/var/www/html/storage/search-indexes"]
VOLUME ["/music", "/var/www/html/storage/search-indexes", "/cache"]


# Copy Apache configuration
COPY apache/site.conf /etc/apache2/conf.d/
COPY apache/httpd.conf /etc/apache2/
COPY apache/www.conf /etc/php83/php-fpm.d/

# Copy php.ini
COPY ./php.ini "$PHP_INI_DIR/php.ini"

# make crontab file
RUN touch /etc/crontabs/www-data

# Apply lalvel optimalizations
RUN cd /var/www/html \
&& php artisan route:cache \
&& php artisan event:cache \
&& php artisan view:cache


ENV FFMPEG_PATH=/usr/bin/ffmpeg \
MEDIA_PATH=/music \
STREAMING_METHOD=x-sendfile \
LANG=en_US.UTF-8 \
LANGUAGE=en_US:en \
LC_ALL=en_US.UTF-8
LC_ALL=en_US.UTF-8 \
APACHE_LOG_DIR=/var/log/apache2

# Setup bootstrap script.
COPY koel-entrypoint /usr/local/bin/
COPY koel-init /usr/local/bin/
ENTRYPOINT ["koel-entrypoint"]
CMD ["apache2-foreground"]
CMD [""]

EXPOSE 80

# Check that the homepage is displayed
HEALTHCHECK --start-period=30s --interval=5m --timeout=5s \
CMD curl -f http://localhost/sw.js || exit 1


9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,15 @@ docker-compose -f ./docker-compose.postgres.yml up -d

## The `koel:init` command

This command is automatically ran when the container starts, but can be disabled if you want to do some manual adjustments first. As such it is often sufficient to provide the needed env variables to the container to setup koel.

For the first installation and every subsequent upgrade, you will need to run the `koel:init` command, which handles migrations and other setup tasks.
For instance, during the first run, this command will generate the `APP_KEY`, create the default admin user, and initialize the database. For subsequent runs, it will apply any new migrations and update the database schema as needed.

In order to run this command, you first need to `exec` into the container (replace `<container_name_for_koel>` with the name of your running Koel container):

```bash
docker exec --user www-data -it <container_name_for_koel> bash
docker exec --user www-data -it <container_name_for_koel> sh
```

Once inside the container, run the `koel:init` command:
Expand Down Expand Up @@ -142,7 +144,7 @@ Once you have generated an `APP_KEY` you can provide it as environment variables

```bash
# Run a container just to generate the key
docker run -it --rm phanan/koel bash
docker run -it --rm phanan/koel sh
# In the container, generate APP_KEY
$ php artisan key:generate --force
# Show the modified .env file
Expand Down Expand Up @@ -188,7 +190,7 @@ For all new songs, the search index will be automatically populated by `php arti

> [!IMPORTANT]
> This list is not exhaustive and may not be up-to-date. See [`.env.example`][koel-env-example] for a complete reference.

- `SKIP_INIT` : set a value to prevent the container from automatically running the init script on startup
- `DB_CONNECTION`: `mysql` OR `pgsql` OR `sqlsrv` OR `sqlite-persistent`. Corresponds to the type of database being used with Koel.
- `DB_HOST`: `database`. The name of the Docker container hosting the database. Koel needs to be on the same Docker network to find the database by its name.
- `DB_USERNAME`: `koel`. If you change it, also change it in the database container.
Expand All @@ -199,6 +201,7 @@ For all new songs, the search index will be automatically populated by `php arti
- `MEMORY_LIMIT`: The amount of memory in MB for the scanning process. Increase this value if `php artisan koel:scan` runs out of memory.
- `LASTFM_API_KEY` and `LASTFM_API_SECRET`: Enables Last.fm integration. See https://docs.koel.dev/3rd-party.html#last-fm
- `SPOTIFY_CLIENT_ID` and `SPOTIFY_CLIENT_SECRET`: Enables Spotify integration. See https://docs.koel.dev/3rd-party.html#spotify
- `OPTIMIZE_CONFIG` Preload and optimize the config. This disables your ability to do config edits while the container is running. If you enable this every config change will require a container restart to apply.

## Volumes

Expand Down
Loading
Loading