ClassicPress Docker Image

Hello,

my name is Marek. I found a ClassicPress on AlternativeTo portal, as I was looking for an alternative to WordPress. CP is what I was looking for :slight_smile: The only thing missing was no Docker Image available. So I spend couple of days preparing an image on my own.
It’s based on php:7.4-apache-bullseye Docker image. I have bundled all php extensions needed. Also apache-mod-security2 + OWASP CRS is on board.
Feel free to test it.

Docker Hub: Docker
GitHub repo: GitHub - marverix/classicpress-docker: ClassicPress in Docker Image

Br,
Marek

6 Likes

After few more days of work, a few more iterations, and tweaks, tag cp1.3.1-rev3 is working pretty fine :slight_smile:

I have added docker-secrets support, and X-FORWARDED-PROTO header to wp-config template.

I have moved all 4 WordPress 5.x instances, that I had under my control, that so far was handled by WordOps. ClassicPress is working fantastic, and I couldn’t ask more. Thank you for your work CP Team!

4 Likes

We’ll be making a page with all the hosting resources available for CP. I will make sure we list your Docker, this is a great option for local testing and production deployment.

I was wondering if this can be updated? The last version is 1.4.4 in the Github repo.
I also came across this:Docker - - if this works, could someone please share a docker config/compose for this? Thanks!

We haven’t made any documentation available for our Docker image yet. It’s new, and we haven’t announced it yet. Maybe @getkoded007 can help.

1 Like

as this moment! the offical docker image for ClassicPress works as expected. here is the docker-compose file if you are using that to deploy a CP site

version: '3.8'

services:

  classicpress:
    image: classicpress/classicpress
    container_name: classicpress
    restart: always
    ports:
      - 8080:80
    environment:
      CLASSICPRESS_DB_HOST: db
      CLASSICPRESS_DB_USER: exampleuser
      CLASSICPRESS_DB_PASSWORD: examplepass
      CLASSICPRESS_DB_NAME: exampledb
    volumes:
      - classicpress:/var/www/html

volumes:
  classicpress:

I didn’t include the mysql or mariadb container that’s something that you chooose on your own and which version of MySQL or MariaDB wil work

1 Like

You can also use the same image for production if you know what you are doing. By default the image uses localhost if you’re on a local machine. If you are interested in using as a production server… you will need to configure a nginx file for your site and certbot if you want let’s encrypt so that’s something that’s doable.

1 Like

Do the AUTH related environmental variables work? example: WORDPRESS_AUTH_SALT

Okay so I made this:

version: '2.1'

services:

  wordpress:
    container_name: ${SITE_NAME}-wp
    image: classicpress/classicpress
    restart: always
    ports:
      - ${SITE_PORT}:80
    environment:
      CLASSICPRESS_DB_HOST: db
      CLASSICPRESS_DB_USER: ${DB_USER}
      CLASSICPRESS_DB_PASSWORD: ${DB_PASSWORD}
      CLASSICPRESS_DB_NAME: ${DB_NAME}
      CLASSICPRESS_AUTH_KEY: ${WP_AUTH_KEY}
      CLASSICPRESS_SECURE_AUTH_KEY: ${WP_SECURE_AUTH_KEY}
      CLASSICPRESS_LOGGED_IN_KEY: ${WP_LOGGED_IN_KEY}
      CLASSICPRESS_NONCE_KEY: ${WP_NONCE_KEY}
      CLASSICPRESS_AUTH_SALT: ${WP_AUTH_SALT}
      CLASSICPRESS_SECURE_AUTH_SALT: ${WP_SECURE_AUTH_SALT}
      CLASSICPRESS_LOGGED_IN_SALT: ${WP_LOGGED_IN_SALT}
      CLASSICPRESS_NONCE_SALT: ${WP_NONCE_SALT}
      CLASSICPRESS_CONFIG_EXTRA: |
        define('WP_DEBUG',false);
        define('WP_CACHE',true);
        define('AUTOSAVE_INTERVAL',300);
        define('EMPTY_TRASH_DAYS',2);
        define('WP_POST_REVISIONS',false);
        define('DISALLOW_FILE_EDIT',true);
        define('DISALLOW_FILE_MODS',true);
        define('FS_METHOD','direct');
    volumes:
      - /docker/appdata/wp/sites/${SITE_NAME}:/var/www/html:rw
      - /docker/appdata/wp/themes:/var/www/html/wp-content/themes
      - /docker/appdata/wp/plugins:/var/www/html/wp-content/plugins
      - /docker/appdata/wp/mu-plugins:/var/www/html/wp-content/mu-plugins
    links:
      - db:db

  db:
    container_name: ${SITE_NAME}-db
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_RANDOM_ROOT_PASSWORD: '1'
    volumes:
      - /docker/appdata/wp/db/${SITE_NAME}:/var/lib/mysql

volumes:
  wordpress:
  db:

These are the environmental variables:

SITE_PORT
SITE_NAME
DB_USER
DB_PASSWORD
DB_NAME
WP_AUTH_KEY
WP_SECURE_AUTH_KEY
WP_LOGGED_IN_KEY
WP_NONCE_KEY
WP_AUTH_SALT
WP_SECURE_AUTH_SALT
WP_LOGGED_IN_SALT
WP_NONCE_SALT

Is there any way things like site title, admin username, password and email can be added to the compose, so we can have something akin to a “one-click” install?
I’m also having trouble getting this thing to work with multisites - - I tried using the enable multisite define in wp-config, and when I went to network setup it said that multisite wouldn’t work on the port (I’m running this in host port 31696). Non-multisite works fine, though.

Please do give a try, we need testers anyways! Feel free let me know here since we don’t have an offical github page for this just yet.

1 Like

Okay so I tested this and it works:

version: '2.1'

services:

  wordpress:
    container_name: ${SITE_NAME}-cp
    image: classicpress/classicpress
    restart: always
    ports:
      - ${SITE_PORT}:80
    environment:
      CLASSICPRESS_DB_HOST: db
      CLASSICPRESS_DB_USER: ${DB_USER}
      CLASSICPRESS_DB_PASSWORD: ${DB_PASSWORD}
      CLASSICPRESS_DB_NAME: ${DB_NAME}
      CLASSICPRESS_AUTH_KEY: ${CP_AUTH_KEY}
      CLASSICPRESS_SECURE_AUTH_KEY: ${CP_SECURE_AUTH_KEY}
      CLASSICPRESS_LOGGED_IN_KEY: ${CP_LOGGED_IN_KEY}
      CLASSICPRESS_NONCE_KEY: ${CP_NONCE_KEY}
      CLASSICPRESS_AUTH_SALT: ${CP_AUTH_SALT}
      CLASSICPRESS_SECURE_AUTH_SALT: ${CP_SECURE_AUTH_SALT}
      CLASSICPRESS_LOGGED_IN_SALT: ${CP_LOGGED_IN_SALT}
      CLASSICPRESS_NONCE_SALT: ${CP_NONCE_SALT}
      CLASSICPRESS_CONFIG_EXTRA: |
        define('WP_DEBUG',false);
        define('WP_CACHE',true);
        define('WP_HTTP_BLOCK_EXTERNAL',true);
        define('WP_ACCESSIBLE_HOSTS','wordpress.org,*.wordpress.org');
        define('AUTOMATIC_UPDATER_DISABLED',true);
        define('WP_AUTO_UPDATE_CORE',false);
        define('DISABLE_WP_CRON',true);
        define('WP_CRON_LOCK_TIMEOUT',60);
        define('IMAGE_EDIT_OVERWRITE',true);
        define('AUTOSAVE_INTERVAL',300);
        define('EMPTY_TRASH_DAYS',2);
        define('WP_POST_REVISIONS',false);
        define('DISALLOW_FILE_EDIT',true);
        define('WP_DEFAULT_THEME','generatepress');
        define('DISALLOW_FILE_MODS',true);
        define('WP_MEMORY_LIMIT','2048M');
        define('FS_METHOD','direct');
    volumes:
      - /docker/appdata/www/${SITE_NAME}/cp:/var/www/html:rw
      - /docker/appdata/wp/themes:/var/www/html/wp-content/themes
      - /docker/appdata/wp/plugins:/var/www/html/wp-content/plugins
      - /docker/appdata/wp/mu-plugins:/var/www/html/wp-content/mu-plugins
    links:
      - db:db

  db:
    container_name: ${SITE_NAME}-db
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_RANDOM_ROOT_PASSWORD: '1'
    volumes:
      - /docker/appdata/www/${SITE_NAME}/db:/var/lib/mysql

volumes:
  wordpress:
  db:

Note that the plugins, mu-plugins and themes folders are common in this yaml, ie they’re shared by all the sites.

1 Like

@getkoded007 This dockerized Classicpress (classicpress/classicpress) doesn’t seem to have GZip enabled. When I tried adding HTACCESS rules for enabling GZip I got 500 errors. How can I enable Gzip?

that’s something you might need to enable youself if u are able to do because from what I can tell. not everyone wants that enable by default.

1 Like

Thanks for clarifying! Could you give me some pointers as to how I may enable it?

the image is using apache, so let me see what information i need to enable that feature!

1 Like

If you haven’t added an additional module to your Docker Image, the user will need to create a new Docker Image on top of yours. Sure that it’s common practice, but it’s totally not practical for users. Additionally, your image contains standard Apache configuration which is on the Top 10 OWASP. In my opinion, this is the responsibility of the image creator to provide a secure image, because most of the users still have very limited knowledge about HTTP headers, cookies settings, etc.
I can update my image for the newest CP and php 8. I’m also a bit surprised that the CP team is inventing the wheel, as I could gladly transfer the ownership of the image to you, but no one even asked. I mean - it’s up to you, but its strange for me tbh.

1 Like

Thanks for updating your docker image!
Just a few questions, if you don’t mind:

  • I didn’t quite understand the UID/GID and why its needed. What values should i set for these? Should they be different for each site/docker container?
  • do all the sites share the same mySQL container or does each site have its own associated db container?
  • how can I access the dockerized mySQL using phpmyadmin?
    Sorry if these have obvious answers, I’m kinda new to containers, just figuring things out. Thanks!

I didn’t quite understand the UID/GID and why its needed. What values should i set for these?
Should they be different for each site/docker container?

I tried to describe why you need UID and GID. It’s related to sharing filesystem between host and docker container. GitHub - marverix/classicpress-docker: ClassicPress in Docker Image
If you look in the instruction, you will see this:

export UID=$(id -u)
export GID=$(id -g)

This will set UID and GIT for you.

do all the sites share the same mySQL container or does each site have its own associated db container?

This is fully up to you. On one hand having a separate SQL instance for each WP instance is gives you more stability and that eg 10 sites do not have single point of failure. On the other hand, you will need ~10x more hardware resources. Personall I would say that if it’s your personal sites that do not need to have ~99,99% uptime, then go with 1 SQL.

how can I access the dockerized mySQL using phpmyadmin?

The easiest solution would be to have phpmyadmin also dockerized. On the official repo there is ready docker compose example how to do it: https://github.com/phpmyadmin/docker#usage-with-docker-compose-and-arbitrary-server

our main focus currently is to have a working classicpress image which we currently have, we don’t need to add phpmyadmin or other images to the official CP official docker hub since we can use the official images such as mailhog, mailcatcher, MySQL, MariaDB and phpMyAdmin.

Our current objective is right now is to create mulitple verions of CP images for PHP, one for 7.4, 8.0, 8.1 and 8.2 and so on. We will eventually create not just one apache server image but we probably will end up creating one for Nginx as well.

When you didn’t reply to the issue on Github in January, I figured it was no longer maintained. So we decided to proceed with our own Docker implementation. We aim to eventually provide the most common implementations that users can deploy (default CP image, Apache, Nginx, LiteSpeed, etc.). We welcome and would appreciate any help you can provide. Feel free to join Slack #docker channel.