A docker image with only the bare essentials needed to run koel. It includes apache and a php runtime with required extensions.
See the Changelog to keep track of changes to the image.
⚠ This container does not include a database. It requires another container to handle the database.
Since Koel supports many databases you are free to choose any Docker image that hosts one of those databases.
koel/docker
(this image) has been tested with MySQL and PostgreSQL.
docker-compose is the easiest way to get started. It will start both the database container and this image.
Clone this repository and edit docker-compose.mysql.yml
. Make sure to replace passwords !
Check out the ./docker-compose.mysql.yml
file for more details.
Then run docker-compose
:
docker-compose -f ./docker-compose.mysql.yml up -d
Clone this repository and edit docker-compose.postgres.yml
. Make sure to replace passwords !
Check out the ./docker-compose.postgres.yml
file for more details.
Then run docker-compose
:
docker-compose -f ./docker-compose.postgres.yml up -d
On the first run, you will need to:
- Generate
APP_KEY
- Create an admin user
- Initialize the database
All these steps are achieved by running koel:init
once:
Replace <container_name_for_koel>
in the command by the actual container name.
docker exec -it <container_name_for_koel> bash
# Once inside the container, you can run commands:
$ php artisan koel:init --no-assets
--no-assets
option tells the init command to skip the build of front-end assets. They are already built by a Github Action in koel's repository, so this step is not necessary.
⚠ From v5.1.0, Koel will no longer ask for a username, email and password for the admin account. Instead, it creates one automatically with the following credentials:
email: [email protected]
password: KoelIsCool
Make sure to change this unsecure password with the user interface (click on your profile picture) or by running the following command:
docker exec -it <container_name_for_koel> php artisan koel:admin:change-password
Create a docker network. It will be shared by Koel and its database.
docker network create --attachable koel-net
Create a database container. Here we will use mysql.
docker run -d --name database \
-e MYSQL_ROOT_PASSWORD=<root_password> \
-e MYSQL_DATABASE=koel \
-e MYSQL_USER=koel \
-e MYSQL_PASSWORD=<koel_password> \
--network=koel-net \
-v koel_db:/var/lib/mysql \
mysql/mysql-server:5.7
Create the koel container on the same network so they can communicate
docker run -d --name koel \
-p 80:80 \
-e DB_CONNECTION=mysql \
-e DB_HOST=database \
-e DB_DATABASE=koel \
-e DB_USERNAME=koel \
-e DB_PASSWORD=<koel_password> \
--network=koel-net \
-v music:/music \
-v covers:/var/www/html/public/img/covers \
-v search_index:/var/www/html/storage/search-indexes \
hyzual/koel
The same applies for the first run. See the First run section.
To be sure to preserve APP_KEY
you can choose to bind-mount the .env
file to your host:
# On your host, create an `.env` file:
touch .env
# Then, you can bind-mount it directly in the container.
docker run -d --name koel \
-p 80:80 \
--mount type=bind,source="$(pwd)"/.env,target=/var/www/html/.env \
hyzual/koel
docker exec -it koel bash
# In the container, init
$ php artisan koel:init --no-assets
Once you have generated an APP_KEY
you can provide it as environment variables to your container to preserve it.
# Run a container just to generate the key
docker run -it --rm hyzual/koel bash
# In the container, generate APP_KEY
$ php artisan key:generate --force
# Show the modified .env file
$ cat .env
# Copy the APP_KEY variable
$ exit
You can then provide the variables to your real container:
docker run -d --name koel \
-p 80:80 \
-e APP_KEY=<your_app_key> \
hyzual/koel
# Even better, write an env-file in your host and pass it to the container
docker run -d --name koel \
-p 80:80 \
--env-file .koel.env \
hyzual/koel
Whenever the music in /music
changes, you will need to manually scan it before koel is able to play it. Run the following command:
docker exec <container_name_for_koel> php artisan koel:sync
If you were running a version of Koel prior to v5.0.2, the search mechanism has changed and needs a step to index songs, albums and artists. Run the following command:
docker exec <container_name_for_koel> php artisan koel:search:import
For all new songs, the search index will be automatically populated by php artisan koel:sync
. No need to run the php artisan koel:search:import
again 🙂.
See .env.example
for reference.
DB_CONNECTION
:mysql
ORpgsql
ORsqlsrv
ORsqlite-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.DB_PASSWORD
: The password credential matchingDB_USERNAME
. If you change it, also change it in the database.DB_DATABASE
:koel
. The database name for Koel. If you change it, also change it in the database.APP_KEY
: a base64 string. It is generated byphp artisan koel:init
or byphp artisan key:generate
. Once you have scanned music, DO NOT CHANGEAPP_KEY
. Songs are identified by a combination ofAPP_KEY
and their path, so ifAPP_KEY
changes, the nextphp artisan koel:scan
will report all songs as changed.FORCE_HTTPS
: if set totrue
, all URLs redirects done by koel will usehttps
. If you have setup a reverse-proxy in front of this container that supportshttps
, set it totrue
.MEMORY_LIMIT
: amount of memory in MB for the scanning process. Set this ifphp artisan koel:scan
runs out of memory.LASTFM_API_KEY
andLASTFM_API_SECRET
: Enable scrobbling to Last.fm. See https://docs.koel.dev/3rd-party.html#last-fm
/music
will contain the music library. Keep in mind that koel needs to scan music before it's able to play it.
/var/www/html/storage/search-indexes
will contain the search indexes. Searching songs, albums and artists leverages this to provide results.
Only HTTP is provided. Consider setting up a reverse-proxy to provide HTTPS support.
Apache's root directory. All koel files will be here. If you exec
into the container, this will be your current directory.