Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: rework Container image, Compose manifest and CI #64

Open
wants to merge 83 commits into
base: main
Choose a base branch
from

Conversation

almereyda
Copy link
Collaborator

@almereyda almereyda commented May 9, 2024

This change request presents a major opinionated rewrite of this repository.

  • adds the list of authors
  • adds a LICENSE
  • adds a dot env file .env to configure Pretalx as a container-native 12 factor app
  • adds cron to the image to be ran in a separate container independently from the host system
  • adds a separate Nginx container to terminate static/ assets and media/
  • adds an example to run Pretalx with plugins
  • adds different Compose manifests for different scenarios, including legacy Docker Compose
  • adds a generic build workflow to easily build different images
  • adds a plugins workflow to build a pretalx-extended image
  • updates CI
  • updates the README
  • updates the database to recommended PostgreSQL
  • updates the default image name to pretalx/pretalx in CI and Compose
  • updates the Pretalx container image from a source build to a release build
  • updates the entrypoint to for regular cases, removes automigrate/-rebuild
  • updates the now unused pretalx.cfg example to be compatible with the changed setup
  • removes supervisor from the container and replaces its function with individual containers per job
  • removes unmaintained reverse proxy examples
  • removes unrelated Ansible
  • removes linux/arm64 build target

closes #21
closes #56
closes #59 ?
closes #62

@almereyda
Copy link
Collaborator Author

almereyda commented May 9, 2024

This PR presents the result of 16 hrs of work to reshape it into a more "production-ready" form. This is achieved by dropping the support for local source builds.

  • Local container builds for developing Pretalx should be implemented with development containers in the upstream repository.

Additionally, following the 12factor.net approach of designing web applications, it is useful to consider the parts of the application self-contained and independent from external systems. Why the reliance on a cron scheduler may be defeating the purpose of separating concerns in containers.

A convention designed for running jobs in distributed systems is to use a worker queue and have it be triggered with timers. Fortunately Celery is already used for dispatching asynchronous tasks. Its Celery Beat feature can also be used to regularly schedule jobs, removing the need for a separate cron container.

I'm especially invested in this, since the cron implementation took a quarter of the time from the overall procedure and is prone to fail in a container.

What could possibly go wrong?

  • Celery Beat is to be implemented upstream as well.

To complete the move towards "cloud-native", distributed application design, it is also advisable to implement the database URL pattern, which had been introduced by Heroku and is of good ease, convenience and use to DevOps people.

Further on, now that the application setup is more decoupled, images are more lightweight and deterministic, due to switching to pinned release versions of Pretalx, it becomes possible to imagine to further

  • automate the image build pipeline, e.g. by reacting to upstream releases and to offer versioned, tagged releases here, too.

I'm thinking of the way how these two repositories react to their upstream, adapted from Node to Python:

In case you agree with the follow ups as outlined above, I'd step ahead and open respective issues.

@almereyda
Copy link
Collaborator Author

More inspiration could be taken from allmende/docker-fiduswriter.

context/default/Dockerfile Outdated Show resolved Hide resolved
export PRETALX_DATA_DIR="${PRETALX_DATA_DIR:-/data}"

PRETALX_FILESYSTEM_LOGS="${PRETALX_FILESYSTEM_LOGS:-/data/logs}"
PRETALX_FILESYSTEM_MEDIA="${PRETALX_FILESYSTEM_MEDIA:-/data/media}"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't these defaults match what's set in the .env.example?

Copy link
Collaborator Author

@almereyda almereyda May 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was adapted from the original image and I guess for now they do not show the container defaults, but rather the application defaults.

I'm open to hearing further opinions on this.

@DASPRiD
Copy link

DASPRiD commented May 9, 2024

This looks generally good to me.

While in a Kubernetes environment I'm used to having CronTab jobs running periodic stuff in containers, I don't see too much harm in having crontab running within the application container. That is, unless someone wants to create replicas of the application container and run the worker things isolated on their own, but I doubt that this would be possible with Pretalx, so this is likely a non issue.

For static file serving I think that nginx as a separate container (or any other simple file server like halverneus/static-file-server) is a good choice, instead of the main container doing the serving.

👍 Overall, I'm happy with these changes.

Could we maybe consider having a GitHub workflow which automates new releases to DockerHub (or GitHub Packages)? This would avoid having bug-fixes merged into main but then not released for several months.

@almereyda
Copy link
Collaborator Author

almereyda commented May 23, 2024

The last two days have brought new image variants, local build scripts, a build pipeline and the proposed migration hints to the README.

Bildschirmfoto vom 2024-05-23 03-33-24

For now, the pipeline can be triggered manually and by releases.

The other push and PR triggers have been removed, until this has been settled a little.

The image variants reintroduce the standalone image for easing the migration in existing setups.

The extended and cron variants from the "stock" image have also been applied to the standalone one for sake of completeness. This means people can potentially remove the external dependency to cron from their existing containerised application setup.

There are also new example contexts to build the application from source, of which one mimics the current state of affairs, namely context/source/standalone/Dockerfile.debian.local, which is included in the overlay compose/build/source/standalone.local.yml.

The one interesting for me to be able to run from main, including the fix for pretalx/pretalx#1773, is compose/build/source/extended.cron.remote.yml.

The README tries to be complete and concise at the same time. Due to the multiple ways to approach the repository, its images, the Compose manifests and also the CI pipeline(s) we cannot be exhaustive here. Maybe the setup is complex enough to consider adding separate documentation to docs/.


This is now ready for merge with approaching the 50th hour. I would leave the click to another maintainer, as I wouldn't want to misuse the gained write-permission to the repository with my own and first contribution.

What's left for future cycles is roughly:

  • Optimisation of the build pipeline, esp. with regards to code deduplication
  • Automation of the build triggers, esp. with regards to upstream releases
  • Reintroduction of PR and push triggers for selected scenarios
  • Individual pipelines per image?
  • Testing and fixing of the functionalities of the containers, esp. for the supervisor and cron variants. Experience tells there might be regressions somewhere.
  • Testing and refinement of the instructions in the readme
  • Testing and documenting a successful migration path from the original standalone image to one of its new variants
  • Testing and documenting a successful migration path from the original source build to one of the new examples

Also new usages for the repository appear within reach:

  • Running containerised end-to-end integration tests for the containers, but also possibly for pretalx itself
  • Examples for using these images with other container schedulers, such as Nomad or Kubernetes

Ultimately, I will also raise conversations upstream about implementing Celery Beat, which would allow to get rid of the cron dependency entirely, and about a containerised development environment and why one might like that.

Copy link
Collaborator

@shoetten shoetten left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, what a huge PR! First of: sorry that i'm not active here. As the story often goes, i don't use pretalx anymore, so i'm not keeping up here and (as the state of this repo shows) i only maintain this on paper..

Nevertheless i took the time to look at your PR. All in all, i like a lot of your changes. Especially breaking up the container images in multiple ones, going more in the direction of one container, one process, as it should be. I left a few comments, but please, just take them as suggestions, nothing important.

I have two main suggestions:

Simplifying
As nice as having all the different variants is, i fear this might be way to much to maintain in the future. If you're up for the job: awesome! Otherwise i would suggest deleting some of them. E.g. do we need the ability to build from source? I know it would be nice to be able to run pretalx:main, but since @rixx wants to release more often, anyways, i don't know if its worth the extra trouble.

Readme

I think most people just want a quick, opinionated "how to run this in the simplest way on production" from the readme. Right now this seems kind of buried. Would you be up for writing a short "how to use in production" and put it up top?
I would also suggest moving everything related to building the containers and developing this repo out of the readme, e.g. in a docs folder.

As is said, please just take these points as suggestions. As these changes go in the right direction overall, i'm not objected to merging as is.

FROM ${BASE_IMAGE}:${BASE_TAG}

# Install system dependencies
RUN apt update && \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the modern way of doing this would be to use multi stage builds. then you can avoid the "install and clean" dance in one giant "RUN" command and copy only the bits over to the next stage that you need

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not proficient enough in picking the artifacts of system packages to the next stage.

Are you suggesting to use multi-stage builds to separate build dependencies and runtime dependencies in the image? How do we differentiate them, e.g. are the -dev apt packages needed to run pretalx or only to build its dependencies during installation?

I didn't dig too deep into the actual implementation of the application yet and was rather suggesting these changes to improve upon in subsequent iterations.

libmemcached-dev \
locales \
nodejs \
npm \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where do we need node and npm? in the source variant?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it's part of the rebuild, rebuild --npm-install and regenerate_css management commands, but please correct me, if I'm wrong.

@@ -0,0 +1,145 @@
# Legacy docker-compose support

This example demonstrates a setup that is compatible with the legacy version of Docker Compose.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe make it more obvious that you mean docker-compose with the dash?

Suggested change
This example demonstrates a setup that is compatible with the legacy version of Docker Compose.
This example demonstrates a setup that is compatible with the legacy version of `docker-compose` v1.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, like in the headline of that section. Eventually it will be good to be ultra-specific and talk about:

the old Docker Compose version 1.x, docker-compose

docker compose -f compose.yml -f compose/local.yml -f compose/traefik.yml config
```

### Live
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Live
### Production

I feel the word "production" is more commonly used, than live?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good spot! You catched me here being weary of that term. I'm choosing live, because for me running a web application is more like publishing a live radio or television show, which needs constant attention, rather than delivering a fixed asset, such as a product. Since we're at it, I'm also weary of concealing the fact of human labour involved by using corporate language, which often dehumanises processes.

If others insist on this, I'm willing to change the phrasing to the more commonplace industry convention.


This repository follows the Pretalx installation instructions as closely as possible.

- [Installation — pretalx documentation](https://docs.pretalx.org/administrator/installation/)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems kind of misleading, since the official docs don't have anything to do with docker at all..

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed.

It should read

This repository imitates the pretalx installation instructions as closely as possible in a containerised environment.

@almereyda
Copy link
Collaborator Author

Thank you for taking the time to look into this. The two points you mention reflect very well the course this has taken:

  • I came here to find a pretalx setup for a live instance.
  • It wasn't existing, so I built on what was there: a source build and a coupled standalone container.
  • I was adding the option to build from versioned releases and then parametrised it, removing prior art.
  • Then I needed support for a custom source build (from a remote git repository) and used the earlier implementation as inspiration, also readding the standalone build and a build from local source.
  • Due to me trying to document these Container development use cases, the readme got out of band.

I agree that the primary use case of this repository should be to show how to run pretalx in a real-world environment, in opposition to its earlier use for building an opinionated standalone image from a tightly coupled git submodule source. The effort of trying to answer to all possible use cases makes the individual choices harder to stand out.

If there would be support by upstream, we would maybe do good in considering to move the Container image + CI manifests for base/ and default/ into the main pretalx repository, in order to build local development containers and the release artifacts where development and releases happen. This repository could then focus on the Compose setup and the image variants.

I agree to decouple the image development instructions into separate docs/ and to render the readme much more accessible for casual visitors.

Allow me to respond to the suggestions in the next two weeks. We are not in a rush here and can take the time to introduce these breaking changes in a well-documented and -tested fashion.

@rixx
Copy link
Member

rixx commented Sep 18, 2024

@almereyda Just a ping: are you still planning to work on this?

@almereyda
Copy link
Collaborator Author

Yes, I got sick back then. I'm currently refactoring and documenting a few Django Compose repositories, from which I plan to backport some of their patterns here, including more simple documentation, as suggested.

I'd say at least another two months, given life circumstances.

@TriplEight
Copy link

TriplEight commented Oct 20, 2024

Thanks a lot for the PR. IMO it's over complicated for docker compose repo. It took me quite a while to understand what goes where.

I made it work: extended version with configured traefik TriplEight#3
Can create a PR here after this one is merged.

@almereyda
Copy link
Collaborator Author

almereyda commented Oct 20, 2024

Great suggestions and ideas in that branch, esp. around the auxiliary services cron, Traefik. I'm also considering using more of Compose's newer include: and extends: statements to organise and layer these setups more clearly. Recent work on Funkwhale ¹ has shown these might come in handy for a Django application with many varying dependencies.

¹ fix(DX): Docker mac compatibility, dynamic DNS + Debian image (!2799) · Merge requests · funkwhale / funkwhale · GitLab

I especially like how you shoretend the healthcheck: commands, the added x-pretalx-depends-on anchor for further deduplication and how you include multiple YAML anchors with <<:

As a style note to TriplEight#3, I would like to suggest to refrain from using the env_file: pattern, where you map the whole environment into each service's container, including all variables present in .env. With calling the variables in the environment: key individually, we only provide the selected needed blend to each service, which are pulled from the .env file. ¹ With avoiding custom configuration and resorting to conventional defaults, we also keep the command to run everything shorter.

Also defining loggin: settings for short-lived development environments appears redundant.

The FQDN for docker.io images were intentionally provided for compatibility with Podman.

I'll be able to return work on this from mid November on, with aiming for a merge in the first two weeks of December.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants