# Docker praktijkvoorbeeld
# Inleiding
# Onderwijs en Onderzoek
In Vlaanderen is hoger onderwijs de exclusieve bevoegdheid van hogescholen en universiteiten, elk met hun eigen opleidingen. Dit noemt men een binair hoger onderwijssysteem – beroeps- en professionele opleidingen aan hogescholen enerzijds en academische opleidingen aan universiteiten of een School of Arts anderzijds. Deze instellingen doen meer dan louter onderwijs. Zo zijn universiteiten zijn gespecialiseerd in wetenschappelijk onderzoek en vaak is dat fundamenteel wetenschappelijk onderzoek – zeg maar onderzoek omwille van de wetenschap, waarbij de verworven kennis niet noodzakelijk of toch niet onmiddellijk tot een praktische toepassing moet leiden. Hogescholen zijn nog altijd primair onderwijsinstellingen, maar zijn decretaal verplicht om daarnaast aan praktijkgericht wetenschappelijk onderzoek (PWO) te doen. De budgetten hiervoor zijn klein in vergelijking met deze van de universiteiten. Sinds 2013 zijn heel wat academische opleidingen van de hogescholen naar de geassocieerde universiteit moeten verhuizen, en zo ook het wetenschappelijk onderzoek dat daar gedaan werd. Toch zijn hogescholen nog altijd bezig met onderzoek en hebben ook de ambitie om hierin een belangrijke speler te worden. Zo herstijlen de hogescholen zich sinds 2019 tot University of Applied Sciences (and Arts) naar analogie met vele andere landen in Europa.
Om de resultaten van praktijkgericht onderzoek naar de bedrijven te laten doorstromen bestaan er de TETRA-project calls van de Vlaamse Overheid. Hiervoor kunnen hogescholen en universiteiten een projectvoorstel indienen en indien dit goedgekeurd wordt dan kent de Vlaamse Overheid hiervoor subsidies toe die de projectinvesteringen in materiaal en mensen grotendeels dekken.
# Onderzoeksproject
AI is onderzoeksgebied waar de Vlaamse Overheid veel interesse in heeft, en waar men de ambitie heeft om aan de top te staan. Daarom dienden een consortium[1] van Universiteit Gent (opens new window) en Arteveldehogeschool (opens new window), meer bepaald de Vakgroep Vertalen Tolken en Communicatie van de Faculteit Letteren en Wijsbegeerte van Universiteit Gent (opens new window) en het Expertisenetwerk Communicatie, Media en Design van samen een TETRA-project in: “SentEMO – Een Multilinguaal, Zelflerend Platform voor Aspectgebaseerde Sentiment- en Emotieanalyse”. VLAIO (opens new window) keurde dit project in 2020 goed.
Dit tweejarig project (2021-2022) zal een platform maken dat tekstuele input – uit bijvoorbeeld sociale media – verwerkt en daaruit met NLP en ML de sentiment (positief, neutraal of negatief) en emotie (Ekman-emoties: woede, afkeer, tevredenheid, vrees, blijdschap, droefheid of verrassing) afleidt en daarvoor de nodige analyse en gegevensvisualisatie voorziet.
# Platform
Het SentEMO-platform bestaat uit een frontoffice en een backoffice die elk op een eigen fysieke server draaien.
De frontoffice is het deel van de applicatie dat toegankelijk is voor de eindgebruikers, de backoffice is het deel van de applicatie die toegankelijk is voor beheerders en waar de eindgebruikers niet komen.
# Frontoffice
De frontoffice bestaat uit een frontend gemaakt met React en een backend gemaakt met Node.js (opens new window) en PostgreSQL (opens new window). De communicatie tussen frontoffice en backoffice verloopt via RabbitMQ (opens new window), die in dit geval deel is van de frontoffice.
De technology stack voor de frontoffice ziet er zo uit:
# Backoffice
Deze bestaat enkel uit een backend gemaakt in Python (opens new window) die de message queue van de frontoffice uitleest en terug wegschrijft.
De technology stack voor de backoffice ziet er zo uit:
# Architectuur
Apache HTTP Server (opens new window) in DMZ. Poort
80wordt doorgestuurd (redirect) naar poort443zodat enkel HTTPS toegelaten is. Deze server werkt als Reverse Proxy. requests op poort443worden doorgestuurd naar Docker (opens new window) poort3000.Docker
- Containers
- Node.js (opens new window)
node_0op poort3000, aangepaste image gebouwd op basis van de officiële imagenode(opens new window). - PostgreSQL (opens new window)
postgresql_0op poort5432, officiële imagepostgres(opens new window). - pgAdmin (opens new window)
pgadmin_0op poort3032, community imagedpage/pgadmin4(opens new window) die de officiële docker image is. - RabbitMQ (opens new window)
rabbitmq_0op poort5672en
RabbitMQ Management UI (opens new window) op poort15672, officiële imagerabbitmq(opens new window).
- Node.js (opens new window)
- Netwerken
- Netwerk
network_0waarbinnen de containers staan en met elkaar kunnen communiceren.
- Netwerk
- Volumes
- Persistent volume voor pgAdmin (opens new window) (
pgadmin_data) - Persistent volume voor postgreSQL (opens new window) (
postgresql_data) - Persistent volume voor RabbitMQ (opens new window) (
rabbitmq_data)
- Persistent volume voor pgAdmin (opens new window) (
- Containers
# Voorbeeld
# Configuratie
# Dockerfile
# Configuratie
./SentEMO-Front-Office/sentemo-front-office/Dockerfile
FROM node:lts-slim AS node_0
ENV TZ Europe/Brussels
EXPOSE 3000
WORKDIR /srv/www/sentemo-front-office
2
3
4
5
6
7
# Updates
./SentEMO-Front-Office/sentemo-front-office/Dockerfile
RUN apt-get update -qq && apt-get install git -qq -y
RUN npm install --global npm@latest
RUN npm install --global --force yarn
2
3
4
5
# Installatie
./SentEMO-Front-Office/sentemo-front-office/Dockerfile
RUN npm install --global --unsafe-perm=true blitz
COPY package.json .
RUN yarn
COPY . .
RUN blitz prisma generate
2
3
4
5
6
7
8
9
# Bouwen
./SentEMO-Front-Office/sentemo-front-office/Dockerfile
RUN yarn build
# Uitvoeren
./SentEMO-Front-Office/sentemo-front-office/Dockerfile
ENTRYPOINT ["yarn"]
CMD ["start"]
2
3
# Volledig bestand
./SentEMO-Front-Office/sentemo-front-office/Dockerfile
FROM node:lts-slim AS node_0
ENV TZ Europe/Brussels
EXPOSE 3000
WORKDIR /srv/www/sentemo-front-office
RUN apt-get update -qq && apt-get install git -qq -y
RUN npm install --global npm@latest
RUN npm install --global --force yarn
RUN npm install --global --unsafe-perm=true blitz
COPY package.json .
RUN yarn
COPY . .
RUN blitz prisma generate
RUN yarn build
ENTRYPOINT ["yarn"]
CMD ["start"]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Compose file
# Networks
./SentEMO-Front-Office/sentemo-front-office/docker-compose.yml
networks:
network_0:
driver: "bridge"
ipam:
driver: default
config:
- subnet: 172.64.0.0/16
gateway: 172.64.0.1
2
3
4
5
6
7
8
# Services
./SentEMO-Front-Office/sentemo-front-office/docker-compose.yml
services:
node_0:
container_name: "node_0"
build:
context: ..
dockerfile: sentemo-front-office/Dockerfile
depends_on:
- "postgresql_0"
ports:
- "3000:3000"
networks:
- "network_0"
pgadmin_0:
container_name: "pgadmin_0"
depends_on:
- "postgresql_0"
environment:
- PGADMIN_CONFIG_STRICT_TRANSPORT_SECURITY_ENABLED=True
- PGADMIN_DEFAULT_EMAIL=«een_e-mailadres»
- PGADMIN_DEFAULT_PASSWORD=«een_wachtwoord»
- PGADMIN_LISTEN_PORT=443
image: "dpage/pgadmin4"
networks:
- "network_0"
ports:
- "3032:443"
restart: "unless-stopped"
volumes:
- "pgadmin_data:/var/lib/pgadmin"
postgresql_0:
container_name: "postgresql_0"
environment:
TZ: "Europe/Brussels"
PGTZ: "Europe/Brussels"
env_file: "../.env.local"
image: "postgres:latest"
ports:
- "5432:5432"
restart: "unless-stopped"
volumes:
- "postgresql_data:/var/lib/postgresql/data"
networks:
- "network_0"
rabbitmq_0:
container_name: "rabbitmq_0"
image: "rabbitmq:management-alpine"
ports:
- "5672:5672"
- "15672:15672"
restart: "unless-stopped"
volumes:
- "rabbitmq_data:/var/lib/rabbitmq"
networks:
- "network_0"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# Volumes
./SentEMO-Front-Office/sentemo-front-office/docker-compose.yml
volumes:
pgadmin_data: {}
postgresql_data: {}
rabbitmq_data: {}
2
3
4
# Volledig bestand
./SentEMO-Front-Office/sentemo-front-office/docker-compose.yml
networks:
network_0:
driver: "bridge"
ipam:
driver: default
config:
- subnet: 172.64.0.0/16
gateway: 172.64.0.1
services:
node_0:
container_name: "node_0"
build:
context: ..
dockerfile: sentemo-front-office/Dockerfile
depends_on:
- "postgresql_0"
ports:
- "3000:3000"
networks:
- "network_0"
pgadmin_0:
container_name: "pgadmin_0"
depends_on:
- "postgresql_0"
environment:
- PGADMIN_CONFIG_STRICT_TRANSPORT_SECURITY_ENABLED=True
- PGADMIN_DEFAULT_EMAIL=«een_e-mailadres»
- PGADMIN_DEFAULT_PASSWORD=«een_wachtwoord»
- PGADMIN_LISTEN_PORT=443
image: "dpage/pgadmin4"
networks:
- "network_0"
ports:
- "3032:443"
restart: "unless-stopped"
volumes:
- "pgadmin_data:/var/lib/pgadmin"
postgresql_0:
container_name: "postgresql_0"
environment:
TZ: "Europe/Brussels"
PGTZ: "Europe/Brussels"
env_file: "../.env.local"
image: "postgres:latest"
ports:
- "5432:5432"
restart: "unless-stopped"
volumes:
- "postgresql_data:/var/lib/postgresql/data"
networks:
- "network_0"
rabbitmq_0:
container_name: "rabbitmq_0"
image: "rabbitmq:management-alpine"
ports:
- "5672:5672"
- "15672:15672"
restart: "unless-stopped"
volumes:
- "rabbitmq_data:/var/lib/rabbitmq"
networks:
- "network_0"
volumes:
pgadmin_data: {}
postgresql_data: {}
rabbitmq_data: {}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# Deployment
De server waarop de containers moeten draaien is een fysieke server van Universiteit Gent (opens new window).
# VPN
De server kan enkel bereikt worden vanaf het netwerk van Universiteit Gent (opens new window). Hiervoor moet de computer van de developer connectie maken met het VPN van Universiteit Gent (opens new window) via Cisco AnyConnect Secure Mobility Client (opens new window).

# Server
Eens met het VPN verbonden kan er via SSH ingelogd worden op de server. Dit doe je door een Terminal – bijv. Windows Terminal of macOS Terminal – te openen op een persoonlijke computer en via CLI de ssh-opdracht te starten. Intern op het netwerk is het IP-adres van de server gekoppeld aan een domeinnaam.
$ ssh «gebruikersnaam»@«domeinnaam»
Bijv.
$ ssh [email protected]
De systeembeheerder heeft een met daarop Ubuntu als besturingssysteem en waarop Git (opens new window) en Docker (opens new window) geïnstalleerd zijn.
Om de configuratie te deployen moet je een beheerdersaccount (Eng. admin account) hebben op de server. Via het VPN kan je vanop je eigen computer inloggen op de server. Eerst moet er connectie gemaakt worden met de server van UGent. Dit gebeurt via SSH over de VPN-verbinding.
# Node.js installeren
Node.js (opens new window) wordt niet enkel als Container gebruikt, het wordt ook rechtstreeks op de server uitgevoerd om bepaalde scripts te runnen. De laatste LTS-versie is meestal de beste keuze.
«gebruikersnaam»@«computernaam»:~$ curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
«gebruikersnaam»@«computernaam»:~$ sudo apt-get install -y nodejs
«gebruikersnaam»@«computernaam»:~$ node --version
v16.13.0
«gebruikersnaam»@«computernaam»:~$ sudo npm install -g [email protected]
«gebruikersnaam»@«computernaam»:~$ npm --version
8.1.2
«gebruikersnaam»@«computernaam»:~$ _
# Code downloaden
De code van docker en het project staat op een repo server. Die kan met Git (opens new window) naar de server gedownload worden. Dit zou ook op een andere manier gekopieerd worden, maar Git is gebruikelijk.
«gebruikersnaam»@«computernaam»:~$ git clone «URL-van-de-repo»
«gebruikersnaam»@«computernaam»:~$ cd SentEMO-Front-Office/
«gebruikersnaam»@«computernaam»:~/SentEMO-Front-Office$ _
Als de code in de toekomst geüpdatet moet worden kan dat met een pull.
«gebruikersnaam»@«computernaam»:~/SentEMO-Front-Office$ git pull
# Environment
Met de teksteditor – bijv. nano of vi – moeten we een .env.local-bestand maken. Dit bestand bevat gevoelige gevens zoals wachtwoorden en accountnamen, waardoor het niet in de code repo opgeslagen mag worden.
./SentEMO-Front-Office/.env.local
DATABASE_URL=postgresql://«gebruikersnaam_van_de_PostgreSQL-gebruiker»:«wachtwoord_voor_de_PostgreSQL-gebruiker»@«IP-adres_PostgreSQL-server»:5432/sentemo_front_office
POSTGRES_PASSWORD=«wachtwoord_nieuwe_PostgreSQL-gebruiker»
POSTGRES_USER=«gebruikersnaam_nieuwe_PostgreSQL-gebruiker»
RABBITMQ_QUEUE_INPUT=SentEMO_input
RABBITMQ_QUEUE_OUTPUT=SentEMO_output
RABBITMQ_URL=amqp://«IP-adres_RabbitMQ-server»
SESSION_SECRET_KEY=«geheime_sleutel»
2
3
4
5
6
7
# Containers starten
De volgorde waarin de containers gestart worden is van belang:
- Databaseserver:
postgresql_0. - Databaseserver UI:
pgadmin_0, is optioneel, maar kan pas werken als de databaseserver werkt. - Message Queue-server:
rabbitmq_0 - Webserver:
node_0
Een container kan pas met een andere container verbinden als die andere al opgestart is.
Een container starten doe je met docker-compose up «containernaam». Omdat we de CLI na het opstarten terug willen vrijgeven gebruiken we de optie --detach, zo blijft de container in de achtergrond verder lopen en kunnen we nieuwe commando’s ingeven.
«gebruikersnaam»@«computernaam»$ cd SentEMO-Front-Office/sentemo-front-office/
«gebruikersnaam»@«computernaam»~/SentEMO-Front-Office/sentemo-front-office$ docker-compose up --detach postgresql_0
«gebruikersnaam»@«computernaam»~/SentEMO-Front-Office/sentemo-front-office$ docker-compose up --detach pgadmin_0
«gebruikersnaam»@«computernaam»~/SentEMO-Front-Office/sentemo-front-office$ docker-compose up --detach rabbitmq_0
«gebruikersnaam»@«computernaam»~/SentEMO-Front-Office/sentemo-front-office$ docker-compose up --detach node_0
Van zodra node_0 gestart is, is de website bereikbaar via https://sentemo.ugent.be (opens new window)
Eem consortium een tijdelijke samenwerking door verschillende organisaties. ↩︎