Pixelfed in Docker

I run pixelfed.de in Docker containers since it’s beginning, but the setup grew over time and became a bit messy.

Now I finally got around to clean it up, and got to a state where – at least I think so – it’s quite simple so I can actually publish it for others to use.

To run your own pixelfed-Instance you’ll need the following docker-compose.yml, a configured env-file and a frontend proxy.


version: '2.1'

    image: zknt/pixelfed
    restart: unless-stopped
      - ./env
      - "app-storage:/var/www/storage"
      - "./env:/var/www/.env"
      - db
      - redis
    # The port statement makes Pixelfed run on Port 8080, no SSL.
    # For a real instance you need a frontend proxy instead!
      - "8080:80"

    image: zknt/pixelfed
    restart: unless-stopped
      - ./env
      - "app-storage:/var/www/storage"
      - "./env:/var/www/.env"
    entrypoint: /worker-entrypoint.sh
      - db
      - redis
      - app
      test: php artisan horizon:status | grep running
      interval: 60s
      timeout: 5s
      retries: 1

    image: zknt/mariadb
    restart: unless-stopped
      - ./env
      - MYSQL_ROOT_PASSWORD=changeMeForProduction
      - "db-data:/var/lib/mysql"

    image: zknt/redis
    restart: unless-stopped
      - "redis-data:/data"



For your env-file use the .env.docker file from the Pixelfed repo. Simply save it as env next to your docker-compose.yml and fill it in.

Important: Leave APP_KEY empty, it will get filled in automatically at the first start. Set DB_HOST to "db", and choose a random password for DB_PASSWORD before the first start.

If you want your instance to federate, set up a working SSL/HTTPS configuration (in your frontend proxy) and fill in the variables on the block starting with ACTIVITY_PUB.

First start

On the first start of everything the database needs to be initialized. This happens automatically, but takes some seconds.

Start everything with docker-compose up -d and wait for it. You can watch the progress of the start with docker-compose logs -f app.

After the start is complete, register your account through the web interface, and run docker-compose exec app php artisan user:admin YOURUSERNAME to grant yourself admin rights.


Do not forget to back up your docker volumes, set up SMTP for mailing out, and set up your frontend proxy. I use Traefik for that.

And a last tip:

If you’re experiencing problems you’ll get help on Mastodon (official account is @pixelfed) or via IRC on Freenode, the channel is #pixelfed.

10 Replies to “Pixelfed in Docker”

  1. db_1 | Uptime: 5 Threads: 7 Questions: 1 Slow queries: 0 Opens: 16 Flush tables: 1 Open tables: 10 Queries per second avg: 0.200
    db_1 | + ‘[‘ 0 -ne 0 ]
    db_1 | + ‘[‘ q ‘!=’ q ]
    db_1 | + ‘[‘ qpixelfed ‘!=’ q ]
    db_1 | + ‘[‘ qpixelfed ‘!=’ q ]
    db_1 | + echo ‘CREATE USER ‘”‘”‘pixelfed'”‘”‘@'”‘”‘%'”‘”‘ IDENTIFIED BY ‘”‘”‘pixelfed'”‘”‘;’
    db_1 | + mysql -u root
    db_1 | + echo ‘GRANT ALL on .* TO ‘”‘”‘pixelfed'”‘”‘@'”‘”‘%'”‘”‘;’
    db_1 | + mysql -u root
    db_1 | ERROR 1064 (42000) at line 1: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ‘* TO ‘pixelfed’@’%” at line 1

  2. worker:
    image: zknt/pixelfed
    restart: unless-stopped
    – ./env
    – “./env:/var/www/.env” <<<— I guess this is wrong.

    1. You’re totally right, that line is supposed to go in the volumes mapping.
      I’ve updated the post, thanks for the notice!

      1. Hi tercean, happy to help. Maybe I’ should also mention that I’m facing a couple of issues to run this docker version in my setup and struggling to find references online: (1) I’m presented with ‘no available preview’ message instead of the actual pictures in the timeline and the post itself, although I can actually see all the pictures in the ‘all posts from…’ section. Worker log tells me horizon is running. (2) I run the service using non-standard port because my 443 and 80 are filtered by the ISP. Although most of the internal links will retain the port info as part of the URL, some links in will strip the port information, mostly post-related actions (https:///p/user/long-number). Is there any way to add the port to the configuration across the board? Any suggestion is welcome.

  3. Can I run this image with my own postgresql and redis server? Would it be enough to comment out the db: and redis: stuff?

  4. Do you know what is going on here?:

    + ‘[‘ ‘!’ -z ‘]’
    app-1 | + cp -r storage.skel/app storage.skel/debugbar storage.skel/framework storage.skel/logs storage.skel/purify storage/
    app-1 | + chown -R www-data:www-data storage/ bootstrap/
    app-1 | + php /wait-for-db.php
    app-1 | Database is up
    app-1 | + [[ ! -e storage/.docker.init ]]
    app-1 | + echo ‘Fresh installation, initializing database…’
    app-1 | Fresh installation, initializing database…
    app-1 | + gosu www-data php artisan key:generate
    app-1 | [2023-11-28 20:12:36] production.ERROR: file_put_contents(/var/www/.env): Failed to open stream: Permission denied {“exception”:”[object] (ErrorException(code: 0): file_put_contents(/var/www/.env): Failed to open stream: Permission denied at /var/www/vendor/laravel/framework/src/Illuminate/Foundation/Console/KeyGenerateCommand.php:109)
    app-1 | [stacktrace]
    app-1 | #0 /var/www/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(254): Illuminate\\Foundation\\Bootstrap\\HandleExceptions->handleError()
    app-1 | #1 [internal function]: Illuminate\\Foundation\\Bootstrap\\HandleExceptions->Illuminate\\Foundation\\Bootstrap\\{closure}()
    app-1 | #2 /var/www/vendor/laravel/framework/src/Illuminate/Foundation/Console/KeyGenerateCommand.php(109): file_put_contents()
    app-1 | #3 /var/www/vendor/laravel/framework/src/Illuminate/Foundation/Console/KeyGenerateCommand.php(82): Illuminate\\Foundation\\Console\\KeyGenerateCommand->writeNewEnvironmentFileWith()
    app-1 | #4 /var/www/vendor/laravel/framework/src/Illuminate/Foundation/Console/KeyGenerateCommand.php(47): Illuminate\\Foundation\\Console\\KeyGenerateCommand->setKeyInEnvironmentFile()
    app-1 | #5 /var/www/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(36): Illuminate\\Foundation\\Console\\KeyGenerateCommand->handle()
    app-1 | #6 /var/www/vendor/laravel/framework/src/Illuminate/Container/Util.php(41): Illuminate\\Container\\BoundMethod::Illuminate\\Container\\{closure}()
    app-1 | #7 /var/www/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(93): Illuminate\\Container\\Util::unwrapIfClosure()
    app-1 | #8 /var/www/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(37): Illuminate\\Container\\BoundMethod::callBoundMethod()
    app-1 | #9 /var/www/vendor/laravel/framework/src/Illuminate/Container/Container.php(662): Illuminate\\Container\\BoundMethod::call()
    app-1 | #10 /var/www/vendor/laravel/framework/src/Illuminate/Console/Command.php(211): Illuminate\\Container\\Container->call()
    app-1 | #11 /var/www/vendor/symfony/console/Command/Command.php(326): Illuminate\\Console\\Command->execute()
    app-1 | #12 /var/www/vendor/laravel/framework/src/Illuminate/Console/Command.php(181): Symfony\\Component\\Console\\Command\\Command->run()
    app-1 | #13 /var/www/vendor/symfony/console/Application.php(1081): Illuminate\\Console\\Command->run()
    app-1 | #14 /var/www/vendor/symfony/console/Application.php(320): Symfony\\Component\\Console\\Application->doRunCommand()
    app-1 | #15 /var/www/vendor/symfony/console/Application.php(174): Symfony\\Component\\Console\\Application->doRun()
    app-1 | #16 /var/www/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(201): Symfony\\Component\\Console\\Application->run()
    app-1 | #17 /var/www/artisan(37): Illuminate\\Foundation\\Console\\Kernel->handle()
    app-1 | #18 {main}
    app-1 | “}
    app-1 |
    app-1 | In KeyGenerateCommand.php line 109:
    app-1 |
    app-1 | file_put_contents(/var/www/.env): Failed to open stream: Permission denied

    1. Your .env file on your host needs to be writeable for the container (uid 33 / gid 33), as the first start generates the application key and writes it to .env

      Best would probably to `chgrp 33; chmod 660 .env` for you

Leave a Reply

Your email address will not be published. Required fields are marked *