How To: Docker mit React und Node
Von Lukas Ganster am 19.06.2022
Docker gibt Entwickler:innenn die Möglichkeit, alle ihre Anwendungen in Containern zu verpacken. Diese Container können auf jedem Rechner ausgeführt werden, auf dem Docker installiert ist und die Applikation laufen kann. Dies ist eine großartige Möglichkeit, einen identen “Klon” einer Codebasis auf mehreren Systemen laufen zu lassen mit dem großen Vorteil, dass man sicher sein kann, dass alle identisch sind.
CI/CD-Workflows und DevOps-Testumgebungen werden durch die Verwendung von Docker, das im Wesentlichen eine Reihe von Softwaretools ist, die gemeinsam genutzt werden können, erheblich verbessert. Kubernetes ist ein weiteres Tool, das für den Betrieb mehrerer Docker-Container verwendet wird, allerdings in einem viel größeren Maßstab. Das wird vor allem relevant, wenn man bei seinen Anwendungen von Skalierbarkeit spricht.
In diesem Beitrag zeige ich, wie man ein NodeJS Express-Backend und ein React-Frontend in einem Docker-Container erstellt und betreibt.
Inbetriebnahme eines Node-Backends in Docker
Bevor ihr beginnt, solltet ihr sicherstellen, dass Docker auf eurem Computer installiert ist und läuft.
Nun navigieren wir in ein Verzeichnis, wo unser Docker-Container platziert werden soll. Anschließend werden folgenden Code-Zeilen ausgeführt.
mkdir my-app-docker
cd my-app-docker
touch docker-compose.yml
mkdir api
cd api
npm init -y
npm i express
touch app.js Dockerfile .dockerignore
cd ..
Wir haben ein Backend namens api eingerichtet und einige Docker-Dateien erstellt. Öffnen wir nun das Projekt in unserem Code-Editor und fügen den untenstehenden Code in die entsprechenden Dateien ein.
Fügen den Code in die Datei docker-compose.yml ein. Die Formatierung der yaml-Datei muss sorgfältig vorgenommen werden, da sonst Docker-Fehler auftreten, wenn versucht wird, die Datei auszuführen.
version: '3.8'
services:
api:
build: ./api
container_name: api_backend
ports:
- '4000:4000'
volumes:
- ./api:/app
- ./app/node_modules
Und folgender Codeblock wird in die app.js – Datei geschrieben und repräsentiert unser Node-Backend.
const express = require('express');
const app = express();
const port = process.env.PORT || 4000;
app.get('/', (req, res) => {
res.send('Home Route');
});
app.listen(port, () =>
console.log(`Server running on port ${port}, http://localhost:${port}`)
);
Anschließend kann man das .dockerignore – File so konfigurieren, dass der node_modules-Ordner, ähnlich wie beim Git-Ignore, nicht mitprotokolliert wird. Einfach folgende Zeile beifügen.
node_modules
Desweiteren wird folgender Code in die Datei Dockerfile hinzugefügt.
FROM node:16-alpine
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
EXPOSE 4000
CMD ["node", "app.js"]
Abschließend wird noch folgender Abschnitt ins package.json – File hinzugefügt:
"scripts": {
"start": "node app.js"
},
(Optional) Nodemon um automatische Server-Restarts bei Änderungen zu ermöglichen
Wenn man möchte, dass der Server jedes Mal neu startet, wenn man eine Änderung an den Dateien im Backend vornimmt, kann man ihn für die Verwendung von Nodemon konfigurieren.
Dazu ist es ausreichend, die Dockerfile– und package.json-Datei im api-Ordner zu aktualisieren.
Aktualisiere den Code in der Dockerdatei mit dem unten stehenden Code. Wir installieren nun Nodemon beim Start und verwenden dev als Ausführungsbefehl.
FROM node:16-alpine
RUN npm install -g nodemon
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
EXPOSE 4000
CMD ["npm", "run", "dev"]
Natürlich muss auch das package.json-File wie folgt aktualisiert werden für die Verwendung Nodemon:
"scripts": {
"start": "node app.js",
"dev": "nodemon -L app.js"
},
Zusammengefasst wurde ein einfacher NodeJS Server mit Express, der auf Port 4000 läuft, aufgesetzt. Wichtig ist hierbei, dass auch der Port 4000 im Docker-Container “verwendet” wird, um sozusagen ein Mapping zu ermöglichen.
Starten des Servers
Um den Server außerhalb eines Docker-Containers (auf herkömmliche Art) mit Node wie gewohnt auszuführen, muss nur der folgende Code in der Kommandozeile eingegeben werden.
Dabei müssen vor allem die Inhalte des api-Ordners berücksichtigt werden. Wenn man http://localhost:4000 aufruft, sollte man die “Home-Route” in seinem Browserfenster sehen.
npm run start
Um die NodeJS Express-App innerhalb von Docker zum Laufen zu bringen, ist ein anderer Befehl erforderlich. Zunächst muss man sich im Stammverzeichnis befinden, in dem sich die Datei docker-compose.yml befindet. Anschließend führen wir den unten stehenden Befehl aus und die Anwendung sollte in einem Docker-Container laufen.
docker-compose up
Man muss natürlich darauf auchten, zuerst den Node-Server zu stoppen, da man nur einen Server auf Port 4000 laufen lassen kann.
Wenn man nun wieder auf http://localhost:4000 geht, sie man ebenso die “Home-Route”. Nur diesmal direkt aus Docker heraus.
Den Server kann man mit dem unten stehenden Befehl stoppen, oder man geht zur Docker-App und stoppt die Ausführung des Containers.
docker-compose down
Aufsetzen des React-Frontends in Docker
Im nächsten Schritt erstellen wir innerhalb unseres Docker-Containers ein React-Frontend. Dafür navigieren wir mittels der Kommandozeile in den Root-Ordner von my-app-docker. Einfach folgende Befehle fürs Setup ausführen:
npx create-react-app client
cd client
touch .dockerignore Dockerfile
Nun fügen wir den untenstehenden Code in die korrespondierenden Files ein:
Diese Zeile kommt, wie gewohnt, ins .dockerignore File:
node_modules
Genauso wie bereits oben, wird auch das Dockerfile File konfiguriert:
FROM node:17-alpine
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
Schließlich aktualisieren wir das docker-compose.yml File im Root-Ordner mit dem untenstehenden Codeblock. Im Gegensatz zu vorhin gibt es jetzt auch eine Sektion am Ende, die für die Einstellungen bzw. Konfigurationen des React-Frontend-Projektes stehen. Hier muss man wieder besonders vorsichtig mit der richtigen Formattierung des YAML-Files sein, um etwaige Docker-Fehler präventiv zu vermeiden.
version: '3.8'
services:
api:
build: ./api
container_name: api_backend
ports:
- '4000:4000'
volumes:
- ./api:/app
- ./app/node_modules
client:
build: ./client
container_name: client_frontend
ports:
- '3000:3000'
volumes:
- ./client:/app
- ./app/node_modules
stdin_open: true
tty: true
Grande finale – Starten der Applikation
Ähnlich wie vorhin kann man mit einem simplem Befehl die Applikation normal (außerhalb von Docker) starten. Sicher gehen, dass man im Folder der Client-App ist und den untenstehenden Befehl ausführen. Wenn man jetzt zu http://localhost:3000 geht, sollte man die Startseite einer Boilerplate-React-App sehen.
npm run start
Um die React-App innerhalb von Docker zum Laufen zu bringen, ist ein anderer Befehl erforderlich. Zunächst muss man sich im Root-Ordner befinden, in dem sich die Datei docker-compose.yml befindet. Anschließend sollte die App innerhalb eines Docker-Containers laufen, indem man den folgenden Befehl ausführen:
Natürlich darf auch hier nicht vergessen werden, die React-App auf Port 3000 zu beenden, da nur immer eine Applikation den Port 3000 verwenden kann.
docker-compose up
Erwartungsgemäß findet man auf http://localhost:3000 danach die laufende Applikation von React.
Schließen lässt sich die Anwendung hier, genauso wie beim Backend mit:
docker-compose down
Mit diesem Setup kann man ein NodeJS-Backend und ein React-Frontend gleichzeitig innerhalb von Docker laufen lassen! Wenn Fehler auftreten, muss man möglicherweise die Docker-Desktop-Anwendung öffnen und alle Images entfernen bzw. neu installieren, die mit diesem Projekt verbunden sind. Dann kann man versuchen, den Befehl docker-compose up erneut auszuführen und mit etwas Glück sollte dieses Mal alles wie erwartet funktionieren.
The comments are closed.