Skip to content

Docker Setup

Robert Konigsberg edited this page Nov 29, 2022 · 10 revisions

Terraforming-mars Docker Installations

Pre-built images

  • ltdstudio/terraforming-mars - as of the time of writing (Jan 2022) an older more stable release, but does not have the latest features and fixes
  • andrewsav/terraforming-mars - bleeding edge image, that is, as of the time of writing is re-built from the main branch several times a day. All new bugs included.

Please note, that like the project itself the images are maintained by volunteers, which keeps happening while they remain interested. Because of this, the images can disappear or stop being updated without warning.

When you run the image with docker run -p 8080:8080 -d <image-name>. It will start the game server listening on the Host port of 8080.

Local set-up

On Ubuntu:

sudo snap install docker
sudo groupadd docker
sudo usermod -aG docker $USER

You might need to log out of your account, believe it or not, and then log back in.

(source: https://www.digitalocean.com/community/questions/how-to-fix-docker-got-permission-denied-while-trying-to-connect-to-the-docker-daemon-socket)

Build a docker image from source and run it

Be sure to navigate to the directory you cloned terraforming-mars to from GitHub.

On Linux:

docker build . -t terraforming-mars
docker run -d \
  --name terraforming-mars \
  -p 8080:8080 \
  -v tm-db:/usr/src/app/db \
  terraforming-mars

On Windows:

docker build . -t terraforming-mars
docker run -d `
  --name terraforming-mars `
  -p 8080:8080 `
  -v tm-db:/usr/src/app/db `
  terraforming-mars

This will start the game server listening on port 8080. If you then point a web browser to http://localhost:8080 you will be on the game homepage.

Simple docker-compose service

The file below is the standard compose file in the repository. For a simple installation, simply navigate to the directory you cloned terraforming-mars to from GitHub and you are ready to start the container.

If you are adding the service to another compose file, be sure the build directory (build: ./) point to the directory containing the Dockerfile from the GitHub repository.

version: "3.7"  
services:
  terraforming-mars:
    container_name: terraforming-mars
    build: ./
    restart: unless-stopped
    ports:
      - "8080:8080"
    security_opt:
      - no-new-privileges:true
    volumes:
      - tm-db:/usr/src/app/db
volumes:
  tm-db:

Start the service and run in the background

docker-compose up -d

docker-compose with Traefik reverse proxy

Traefik labels formatted for Traefik v2. Build directory (build: ./) points to the directory containing the Dockerfile from the GitHub repository.

Replace:

  • t2_proxy: Your external network defined in Traefik docker-compose service
  • traefik (depends_on) : name of your Traefik service
  • websecure: name of desired Traefik entry point(s)
  • terraforming-mars.$DOMAINNAME: desired host name for Traefik to forward to web app
services:

######### Define Traefik service here ###########

  terraforming-mars:
    container_name: terraforming-mars
    build: ./
    restart: unless-stopped
    networks:
      - t2_proxy
    security_opt:
      - no-new-privileges:true
    depends_on:
      - "traefik"
    volumes:
      - tm-db:/usr/src/app/db
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=t2_proxy"
      - "traefik.http.routers.terraforming-mars.entrypoints=websecure"
      - "traefik.http.routers.terraforming-mars.rule=Host(`terraforming-mars.$DOMAINNAME`)"
      - "traefik.http.routers.terraforming-mars.service=terraforming-mars"
      - "traefik.http.routers.terraforming-mars.tls=true"
      # To use certs uncomment below and replace "letsencrypt" with the resolver name you configured on the traefik side
      #- "traefik.http.routers.terraforming-mars.tls.certresolver=letsencrypt"
      #- "traefik.http.routers.terraforming-mars.tls.domains[0].main=terraforming-mars.$DOMAINNAME"
      # If you configured traefik TLS options replace "default" with the options name and uncommend line below
      #- "traefik.http.routers.terraforming-mars.tls.options=default"
      - "traefik.http.services.terraforming-mars.loadbalancer.server.port=8080"
      - "traefik.http.services.terraforming-mars.loadbalancer.server.scheme=http"
volumes:
  tm-db:

Start the service and run in the background

docker-compose up -d

docker-compose 'semi-production' setup with postgres and nginx (with BasicAuth)

Postgres ssl cert setup

For additional certificate generation options refer to official postgres docs

# Create your 'site' repository, for example /opt/site-terraforming-mars with certs subfolder
mkdir -p /opt/site-terraforming-mars/certs
cd /opt/site-terraforming-mars
# Find your machine hostname
cat /etc/hostname
# Generate self-signed (basic ssl setup) certificates
openssl req -new -x509 -days 365 -nodes -text -out certs/server.crt -keyout certs/server.key -subj "/CN=<hostname>"
# Change mode of the server.key to 0600
chmod 0600 certs/server.key

Generate ssl certificates for nginx

# While still inside of your site repository folder (sidenote, it should be possible to use the postgres certs for this, just not a good practice)
openssl req -x509 -newkey rsa:4096 -keyout certs/nginx-key.pem -out certs/nginx-cert.pem -days 365 -nodes

Create .htpasswd file for the BasicAuth To generate the user credentials use htpasswd generator online (use salted MD5) or generate it manualy in the command line. Save the .htpasswd file in the site repository, nginx-conf folder. Note: MD5 (even salted, is not safe, neither is BasicAuth, use with caution, do not leave open to internet)

Create nginx server configuration (in this example, it is located in your site repository inside of nginx-conf folder)

# HTTPS
server {
  listen 443 ssl;
  server_name _;
  server_tokens off;

  # Certificate location inside of the docker container
  ssl_certificate conf.d/ssl/nginx-cert.pem;
  ssl_certificate_key conf.d/ssl/nginx-key.pem;
  ssl_session_tickets off;

  add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
  add_header X-Frame-Options DENY;
  add_header X-Content-Type-Options nosniff;

  location / {
    # BasicAuth section, 
    auth_basic "Restricted Content";
    auth_basic_user_file /etc/nginx/.htpasswd;
    # Specify where the server backend is listening
    proxy_pass http://<host_machine_name/ip/localhost>:8765/;
    # Proxy location parameters
    proxy_redirect off;
    proxy_buffering off;
    proxy_http_version 1.1;
    proxy_set_header Connection "Keep-Alive";
    proxy_set_header Proxy-Connection "Keep-Alive";
    proxy_cache_bypass $http_upgrade;
  }
}

Create docker-compose.yaml configuration

version: '3'
services:
  # Server backend
  terraforming-mars:
    # The image can be either built localy (by cloning repo and running 'docker build -t terraforming-mars .') and taged for example 'terraforming-mars' (this option is valid especially when server app is needed to run on ARM architectures)
    # Or one of the above mentioned pre-built images can be used
    image: terraforming-mars
    restart: on-failure:3
    # Preferable on linux, use docker networks on Windows/Mac
    network_mode: host
    # Ensure postgres is running before starting this container
    depends_on:
      - mars-postgres
    environment:
      POSTGRES_HOST: postgresql://<postgres_username>:<postgres_password>@<host_machine_name/ip/localhost>/terraforming-mars
      NODE_ENV: production
      PORT: 8765
    # Limit stdout logs of the docker container
    logging:
      options:
        max-size: 10m

  # Production database
  mars-postgres:
    image: postgres:14.5
    restart: on-failure:3
    network_mode: host
    # Need to enable ssl and point to the certificates
    command: >
      -c ssl=on 
      -c ssl_cert_file=/var/lib/postgresql/server.crt
      -c ssl_key_file=/var/lib/postgresql/server.key
    # User mapping from the host to the container (postgres user is 999, see `cat /etc/passwd` on host for the desired user id)
    user: "1000:999"
    environment:
      POSTGRES_USER: <postgres_username>
      POSTGRES_PASSWORD: <postgres_password>
      POSTGRES_DB: terraforming-mars
    volumes:
      - /path/to/certs/server.crt:/var/lib/postgresql/server.crt:ro
      - /path/to/certs/server.key:/var/lib/postgresql/server.key:ro
      - /data/mars-postgres:/var/lib/postgresql/data
    logging:
      options:
        max-size: 10m

  # Nginx webserver
  nginx:
    image: nginx:stable
    restart: on-failure:3
    network_mode: host
    volumes:
        - /path/to/nginx-conf/:/etc/nginx/conf.d/
        - /path/to/nginx-conf/.htpasswd:/etc/nginx/.htpasswd
        - /path/to/certs/nginx-key.pem:/etc/nginx/conf.d/ssl/nginx-key.pem
        - /path/to/certs/nginx-cert.pem:/etc/nginx/conf.d/ssl/nginx-cert.pem
    logging:
      options:
        max-size: 10m
docker-compose up -d
# Or with newer docker versions
docker compose up -d

Configuration

For more "production-like" usage consider the following:

  • You can customise your instance with environment variables
  • For the database, you probably should not use sqlite or json files. Read more here
  • To improve performance, you can run with environment variable NODE_ENV set to production
  • Environment variables have to be defined in the docker-compose file. For example POSTGRES_HOST=${POSTGRES_HOST}. This forwards the .env variable to docker