Skip to main content

Docker Compose Setup

Getting Started with Docker Compose

  1. Install Docker Desktop or Docker Engine and Docker CLI with the Docker Compose Plugin (docker compose command).

    We DON'T support the usage of the Compose standalone binary (docker-compose command) as its installation method is no longer supported by Docker.

    We recommend the latest version of Docker Desktop or Docker Engine and Docker CLI with Docker Compose Plugin. The minimum version for Docker Compose is 1.27.0+ as of this version the latest Compose file format is supported.

  2. Check that all local network ports used by Docker Compose are free (e.g. you haven't started a local MySQL server when you would like to start a Docker Compose instance of MySQL).

  3. From the repository root, run:

    docker compose --env-file .env -f docker/docker-compose.yml pull
    docker compose --env-file .env -f docker/docker-compose.yml up
  4. Open the Artemis instance in your browser at https://localhost

  5. Run docker compose --env-file .env -f docker/docker-compose.yml down to stop and remove the docker containers

Other Docker Compose Setups

Overview of the Artemis Docker / Docker Compose structure
Overview of the Artemis Docker / Docker Compose structure

The easiest way to configure a local deployment via Docker is a deployment with a docker compose file. In the directory docker/ you can find the following docker compose files for different setups:

  • artemis-dev-mysql.yml: Artemis-Dev-MySQL Setup containing the development build of Artemis and a MySQL DB
  • artemis-dev-postgres.yml: Artemis-Dev-Postgres Setup containing the development build of Artemis and a PostgreSQL DB
  • artemis-dev-local-vc-local-ci-postgres.yml: Artemis-Dev-LocalVC-LocalCI-Postgres Setup adding the integrated code lifecycle (LocalVC, LocalCI, and a build agent) on top of the dev build, so that programming exercises work. This is the setup behind Try Artemis
  • artemis-dev-local-vc-local-ci-mysql.yml: the same with a MySQL DB
  • artemis-prod-mysql.yml: Artemis-Prod-MySQL Setup containing the production build of Artemis and a MySQL DB
  • artemis-prod-postgres.yml: Artemis-Prod-Postgres Setup containing the production build of Artemis and a PostgreSQL DB
  • monitoring.yml: Prometheus-Grafana Setup containing a Prometheus and Grafana instance
  • mysql.yml: MySQL Setup containing a MySQL DB instance
  • nginx.yml: Nginx Setup containing a preconfigured Nginx instance
  • postgres.yml: Postgres Setup containing a PostgreSQL DB instance

Example command to run such setups, from the repository root:

docker compose --env-file .env -f docker/artemis-dev-postgres.yml up

Credentials for the Prod Setups

The dev setups start without any configuration. The prod setups - and docker-compose.yml, which mirrors one of them - need credentials of your own: they activate the prod profile, and docker/artemis/config/prod.env deliberately keeps placeholders that Artemis rejects at startup, because a credential committed to this repository can be read by everyone.

Keep your values in a file of your own, for example docker/artemis/config/local-secrets.env, which is not tracked:

JHIPSTER_SECURITY_AUTHENTICATION_JWT_BASE64SECRET="<output of: openssl rand -base64 64 | tr -d '\n'>"
ARTEMIS_USERMANAGEMENT_INTERNALADMIN_PASSWORD="<a unique password>"

If your setup also activates localvc without localci - the Jenkins with LocalVC shape - add a build-agent git password of your own, because the shipped one is rejected as well:

ARTEMIS_VERSIONCONTROL_BUILDAGENTGITPASSWORD="<a unique password, kept in sync with Jenkins>"

Do not set it where localci is active: such a node refuses to start with it, because its build agents authenticate per build job and need no shared secret. See Build Agent Authentication.

Hand the file to the setup with a small override file, docker/local-secrets.yml:

services:
artemis-app:
env_file:
- ./artemis/config/local-secrets.env
docker compose --env-file .env -f docker/artemis-prod-postgres.yml -f docker/local-secrets.yml up

The docker/test-server-*.yml setups take a full replacement for prod.env through ARTEMIS_ENV_FILE, so there you point that variable at your own copy of prod.env rather than at a file that only holds the credentials. See Security for the properties that are validated. If you just want a running Artemis without configuring anything, use one of the dev setups.

Base Services

For each service being used in these docker compose files, a base service (containing similar settings) is defined in the following files:

  • artemis.yml: Artemis Service
  • mysql.yml: MySQL DB Service
  • nginx.yml: Nginx Service
  • postgres.yml: PostgreSQL DB Service
  • jenkins.yml: Jenkins Service

Testing Services

The following services can be used for testing email and SAML2 authentication locally. They can be run standalone (when running Artemis from IntelliJ or ./gradlew bootRun) or combined with a containerized Artemis setup.

  • mailpit.yml: Mailpit Service (email testing tool, web UI at http://localhost:8025)
  • saml-test.yml: Keycloak Service (SAML2 Identity Provider for testing SAML features, admin console at http://localhost:9080)
  • local-development.yml: Combined setup that includes both Mailpit and Keycloak

Standalone Usage (Non-Containerized Artemis)

When running Artemis from IntelliJ or via ./gradlew bootRun, start only the infrastructure services in Docker:

# Email testing only
docker compose --env-file .env -f docker/mailpit.yml up

# SAML2 testing only
docker compose --env-file .env -f docker/saml-test.yml up

# Both services
docker compose --env-file .env -f docker/local-development.yml up

# Or selectively from the combined file
docker compose --env-file .env -f docker/local-development.yml up mailpit
docker compose --env-file .env -f docker/local-development.yml up keycloak

Then configure Artemis to connect to these services via application-local.yml. See the dedicated setup guides for detailed instructions:

  • Mailpit Setup — Email testing configuration and troubleshooting
  • Keycloak SAML2 Setup — SAML2 Identity Provider configuration, signing credentials, and troubleshooting

Folder Structure

Base services (compose file with just one service) and setups (compose files with multiple services) should be located directly in docker/.

Additional files like configuration files, Dockerfile, ... should be in a subdirectory with the base service or setup name (docker/<base service or setup name>/).

Artemis Base Service

Everything related to the Docker Image of Artemis (built by the Dockerfile) can be found in the Server Setup section. All Artemis-related settings changed in Docker Compose files are described here.

The artemis.yml base service (e.g. in the artemis-prod-mysql.yml setup) defaults to the latest Artemis Docker Image tag in your local docker registry.

  • If you want to build the checked-out version run docker compose build artemis-app before starting Artemis.
  • If you want a specific version from the GitHub container registry change the image: value to the desired image for the artemis-app service and run docker compose pull artemis-app.

Debugging with Docker

See the Debugging with Docker section for detailed information. In all development docker compose setups like artemis-dev-mysql.yml Java Remote Debugging is enabled by default.

Service, Container and Volume Names

Service names for the usage within docker compose are kept short, like mysql, to make it easier to use them in a CLI.

Container and volume names are prepended with artemis- in order to not interfere with other container or volume names on your system.

Get a Shell into the Containers

  • app container: docker compose exec artemis-app bash or if the container is not yet running: docker compose run --rm artemis-app bash
  • mysql container: docker compose exec mysql bash or directly into MySQL docker compose exec mysql mysql

Analogous commands apply to other services.

Other Useful Commands

  • Start a setup in the background: docker compose up -d

  • Stop and remove containers of a setup: docker compose down

  • Stop, remove containers and volumes: docker compose down -v

  • Remove Artemis-related volumes/state: docker volume rm artemis-data artemis-mysql-data

    This is helpful in setups where you just want to delete the state of Artemis.

  • Stop a service: docker compose stop <name of the service> (restart via docker compose start <name of the service>)

  • Restart a service: docker compose restart <name of the service>

  • Remove all local Docker containers: docker container rm $(docker ps -a -q)

  • Remove all local Artemis Docker images: docker rmi $(docker images --filter=reference="ghcr.io/ls1intum/artemis:*" -q)

Using Traefik as a Reverse Proxy

If you want to use Traefik as a reverse proxy for your Artemis instance, you can configure your setup using a single traefik.toml file and a docker-compose.yml file.

The traefik.toml file should be located in the same directory as the docker-compose.yml file. You should also ensure that an acme.json file exists within your directory. The acme.json file is used to store the certificates generated by Traefik. Thus, the permissions of the acme.json file should be set to 600 for root.

Traefik Configuration

The traefik.toml file should be configured as follows:

[global]
checkNewVersion = true
sendAnonymousUsage = false

[log]
level = "INFO"

[api]
dashboard = true
insecure = false

[entryPoints]
[entryPoints.web]
address = ":80"

[entryPoints.websecure]
address = ":443"

[certificatesResolvers.customresolver.acme]
email = "your-mail-address-here"
storage = "/etc/traefik/acme/acme.json"
[certificatesResolvers.customresolver.acme.httpChallenge]
# used during the challenge
entryPoint = "web"
[entryPoints.web.http.redirections.entrypoint]
to = "websecure"
scheme = "https"

[acme]
onHostRule = true

[providers.docker]
endpoint = "unix:///var/run/docker.sock"
exposedByDefault = false
network = "artemis-net" # name of the network in the docker-compose.yml file

[accessLog]
[accesslog.fields.names]
StartUTC = "drop"

Docker Compose Configuration with Traefik

The docker-compose.yml file could look like this for an Artemis, Jenkins and MySQL setup with Traefik as a reverse proxy:

services:
traefik:
image: traefik
container_name: "traefik"
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- "./traefik.toml:/etc/traefik/traefik.toml:ro"
- "./acme.json:/etc/traefik/acme/acme.json"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
- artemis-net
environment:
- TZ=Europe/Berlin
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.entrypoints=websecure"
- "traefik.http.routers.api.tls=true"
# Manage Access to the Traefik Dashboard. Replace <<USERNAME>> and <<PASSWORD_HASH>> with your credentials.
# The dashboard will be available at https://<<ARTEMIS_HOST_NAME>>/dashboard/
# Artemis will be available at another domain: https://<<ARTEMIS_SERVER_NAME>>/
# If you don't want to use the dashboard, you can remove the following lines and disable the dashboard in the traefik.toml file.
- "traefik.http.routers.api.rule=Host(`${ARTEMIS_HOST_NAME}`) && (PathPrefix(`/api/`) || PathPrefix(`/dashboard/`)) || Path(`/dashboard`) || Path(`/api`)"
- "traefik.http.middlewares.api-redirect.redirectregex.regex=^https?://([^/]+)(/[^/]+)$"
- "traefik.http.middlewares.api-redirect.redirectregex.replacement=https://$$1$$2/"
- "traefik.http.routers.api.service=api@internal"
- "traefik.http.routers.api.middlewares=api-redirect,api-auth"
- "traefik.http.middlewares.api-auth.basicauth.users=<<USERNAME>>:<<PASSWORD_HASH>>"

jenkins:
image: jenkins/jenkins:lts
container_name: "jenkins"
restart: unless-stopped
user: root
volumes:
- ./data/jenkins/home:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock
- /usr/bin/docker:/usr/bin/docker:ro
- /usr/bin/com.docker.cli:/usr/bin/com.docker.cli:ro
ports:
- "50000:50000"
networks:
- artemis-net
labels:
- "traefik.enable=true"
- "traefik.http.routers.jenkins.rule=Host(`${JENKINS_SERVER_NAME}`)"
- "traefik.http.routers.jenkins.entrypoints=websecure"
- "traefik.http.routers.jenkins.tls=true"
- "traefik.http.routers.jenkins.tls.certresolver=customresolver"
- "traefik.http.services.jenkins.loadbalancer.server.port=8080"

artemis:
image: ghcr.io/ls1intum/artemis:${ARTEMIS_VERSION}
container_name: "artemis"
restart: unless-stopped
depends_on:
artemis-db:
condition: service_started
jenkins:
condition: service_started
volumes:
- ./data/artemis-be/config:/opt/artemis/config
- ./data/artemis-be/data:/opt/artemis/data
- ./branding:/opt/artemis/public/content:ro
ports:
- "22:22"
environment:
- spring.profiles.active=${PROFILES}
- SPRING_DATASOURCE_URL=jdbc:mysql://artemis-db:3306/Artemis?createDatabaseIfNotExist=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf8&useSSL=false&useLegacyDatetimeCode=false&serverTimezone=UTC
networks:
- artemis-net
labels:
- "traefik.enable=true"
- "traefik.http.routers.artemis.rule=Host(`${ARTEMIS_SERVER_NAME}`)"
- "traefik.http.routers.artemis.entrypoints=websecure"
- "traefik.http.routers.artemis.tls=true"
- "traefik.http.routers.artemis.tls.certresolver=customresolver"
- "traefik.http.services.artemis.loadbalancer.server.port=8080"

artemis-db:
image: mysql:9.7.2
container_name: "mysql"
restart: unless-stopped
volumes:
- ./data/artemis-db:/var/lib/mysql
environment:
- MYSQL_ALLOW_EMPTY_PASSWORD=yes
- MYSQL_DATABASE=Artemis
command: mysqld --lower_case_table_names=1 --tls-version='' --character_set_server=utf8mb4 --collation-server=utf8mb4_unicode_ci --explicit_defaults_for_timestamp
networks:
- artemis-net
cap_add:
- SYS_NICE

networks:
artemis-net:
name: artemis-net
Search documentation