Docker omgeving (Dutch)

Door een aantal problemen met het normaal hosten van de mijncmd backend omgeving, moest ik kijken naar andere oplossingen. Hierdoor kwam ik bij docker. Docker moest mij helpen om een schaalbare oplossing te vinden voor het hosten van mijn Elixir applicatie met SSL Certificaat. In deze post ga ik uitleggen wat ik heb gedaan om dit goed in te richten.

Wat is nodig

Oke, voordat ik begon met het inrichten van deze mooie docker omgeving. Ging ik eerst kijken naar wat ik nodig had en hoe ik de problemen die ik had op zou lossen. Voor het werkend krijgen van een Elixir applicatie heb je ten eerste Elixir zelf nodig. Omdat ik in mijn applicatie ook afbeeldingen bewerk en modify, moet ik ook een package installeren die dit kan. Hiervoor wordt Imagemagick gebruikt. Daarnaast is het ook handig om data op te kunnen slaan. Dit gebeurd met behulp van PostgreSQL. Hiertussen moet een connectie gemaakt worden zodat de backend kan communiceren met de database. Naast Elixir en PostgreSQL had ik ook iets nodig om te buitenkant gebruik te laten maken van de applicatie, een Proxy. Voor deze proxy heb ik gebruik gemaakt van Traefik, hiermee kon ik naast het reguleren van netwerk verkeer, ook een SSL-Certificaat toevoegen. Dit was dus een win win situatie. Met Traefik erbij had ik alles wat ik nodig had overzichtelijk. Er was een plan en het was tijd om de boel in te richten.

De inrichting

Bij het inrichten van mijn docker omgeving heb ik eerst de nodige packages geïnstalleerd die ervoor moeten zorgen dat de backend in ieder geval kan compilen. Om een niet al te zware omgeving te maken, heb ik gekozen voor de alpine version van elixir. Hiervoor moest ik ook de alpine versies van de packages installeren. Gelukkig is docker zo slim dat ie zelf weet hoe dat werkt. Hieronder zie je hoe mijn dockerfile eruit ziet voor het installeren, compilen en starten van de applicatie. Als het goed is valt het ook op dat poort 4000 exposed wordt. Dit is voor Traefik om te weten waar hij naar moet doorverbinden.

ARG ALPINE_VERSION=3.13

FROM elixir:1.11-alpine as elixir_alpine

RUN apk add --update-cache postgresql-client build-base
RUN apk add --no-cache file
RUN apk --update add imagemagick

RUN mix do local.hex --force, local.rebar --force

WORKDIR /app

COPY . .

FROM elixir_alpine AS development

RUN mix do deps.get, compile

EXPOSE 4000

RUN ["chmod", "+x", "./entrypoint.sh"]
ENTRYPOINT ["sh", "./entrypoint.sh"]

Dockerfile met installatie van applicatie Oke, dus de applicatie kan nu in ieder geval compilen en runnen. Poort 4000 staat open  en alles staat klaar om ook echt gebruikt te worden. Het is nu tijd voor mijn docker compose bestand. In mijn docker compose bestand installeer ik Postgres, gebruik ik mijn Dockerfile om de backend te starten, leg ik een connectie tussen de backend en postgres en als kers op de taart, installeer ik ook nog eens traefik met de daarbij nodige configuraties. Voordat ik hier uitleg over ga geven, laat ik het eerst even zien.

version: '3.8'
 
services:
  mijncmd:
    container_name: mijncmd
    networks:
      - traefik-global-proxy
      - backend
    build:
      context: .
      target: development
    environment:
      DATABASE_USER: postgres
      DATABASE_USER_PASSWORD: postgres
      DATABASE_NAME: mijncmd_dev
      DATABASE_PORT: 5432
      DATABASE_HOST: postgres
      DATABASE_SSL: 'false'
      PORT: 4000
      SECRET_KEY_BASE: 'wWNVNM19yWwqL2q2EAoavuYDgYP0Rh2RWq06clo5+fif/ckpk3TnKRepT62OAkNo'
      URL_HOST: localhost
    labels:
      - 'traefik.enable=true'
      - 'traefik.frontend.rule=Host:mijncmd.local'
      - 'traefik.http.routers.mijncmd.rule=Host(`mijncmd.docker.localhost`)'
      - 'traefik.http.routers.mijncmd.entrypoints=websecure'
      - 'traefik.http.routers.mijncmd.tls.certresolver=letsencrypt'
    depends_on:
      - postgres
    volumes:
      - ./lib:/app/lib
      - ./test:/app/test
      - ./priv:/app/priv
      - ./uploads:/app/uploads
      - /app/deps/
  postgres:
    image: postgres:12.6
    networks:
      - backend
    ports:
      - '5432:5432'
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: postgres
      POSTGRES_USER: postgres
  traefik:
    image: traefik:v2.4
    networks:
      - traefik-global-proxy
    ports:
      - '80:80'
      - '443:443'
      - '8080:8080'
    volumes:
      - './traefik/traefik.toml:/etc/traefik/traefik.toml'
      - './letsencrypt:/letsencrypt'
      - /var/run/docker.sock:/var/run/docker.sock
volumes:
  postgres_data: {}
 
networks:
  traefik-global-proxy:
    external: true
  backend:

Docker-compose.yml bestand (wachtwoorden zijn live anders) Oke, laten we van boven naar beneden gaan gaan. Als eerste start ik de backend omgeving onder de naam mijncmd, deze geef ik environment variables mee die gebruikt worden om connectie te maken met de database en aangeven wat de secret key etc. is. De backend omgeving is publiek beschikbaar, daarom moet deze toegevoegd worden aan de traefik-global-proxy netwerk. Maar voor verbinding is er ook een intern netwerk opgezet backend genaamd. Hierdoor kunnen mensen van buitenaf niet bij de database komen. Daarom worden allebei de netwerken toegevoegd onder de networks tab. Na het instellen van de netwerk toegang en de environment variables was het tijd om traefik in te stellen. Onder het kopje labels laat ik Traefik weten dat de omgeving gebruikt moet worden, een hostnaam heeft van mijncmd.docker.localhost en als laatste een ssl certificaat aan moet vragen bij Let's encrypt. Dit gaat allemaal volledig automatisch en werk uitstekend. Bij de liveserver hoeft alleen de hostnaam veranderd te worden naar de domeinnaam die gebruikt wordt. Nu traefik gelinkt is, hoeven we alleen nog maar aan te geven welke mappen gelinkt moeten worden met de computer zelf zodat er ook live dingen veranderen, en klaar is kees. De backend omgeving werkt. Nu is het tijd voor de database, al is dat niet veel speciaals. De image wordt aangegeven en de inloggegevens gedefineerd, dat samen met de interne netwerk is eigenlijk alles wel. Dus kunnen we snel naar traefik. Hier haal ik ook weer de image naar binnen, maar geef ik ook aan waar mijn configuratie staat. Ik heb namelijk een los bestand aangemaakt voor Traefik, hierin geef ik aan welk netwerk er gebruikt moet worden en hoe de certificaten aangevraagd moeten worden.

Als je zo kijkt is het niet heel veel werk om een docker omgeving in te richten. Maar je moet er toch echt even voor zitten, het kost veel moeite en onderzoek om alles echt goed voor elkaar te hebben. Misschien dat je nog iets hebt geleerd van deze post.