Verbind twee Docker containers met hun eigen Docker Compose bestanden
De provider container creëert een Docker netwerk dat gebruikt kan worden door een consumer container.
Ik wilde een netwerk opzetten tussen een database Docker container en een applicatie Docker container, die beide hun eigen Docker Compose bestanden hebben. En ik wilde er ook zeker van zijn dat ik het goed doe voordat ik dit implementeer in de eigenlijke docker-compose bestanden. Test eerst baby ...
Ik heb dit enige tijd geleden ook gedaan, maar moest er nog eens naar kijken omdat Docker Compose nu een naam optie heeft in de netwerken sectie. Ik schrijf deze post om te documenteren hoe ik het deed, hoop dat je het ook nuttig vindt.
Twee containers en commando's om te testen
In deze opstelling gebruik ik twee containers:
- container#1: de database container
- container#2: de applicatie container
Een leuke tool om met containers en netwerken te spelen is het Busybox image. Het is klein en bevat veel netwerkcommando's.
Database container
De database container (de provider) moet een deamon bevatten die luistert naar inkomende verbindingen. In de applicatie container (de consument) draaien we een programma dat de deamon in de database container aanroept.
Voor het luisteren (een echte database deamon luistert) probeerde ik eerst het voor de hand liggende netcat commando, bijvoorbeeld als er geluisterd wordt naar poort 1234:
nc -l -p 1234
Maar het bleek dat netcat eindigde toen de verbinding werd gesloten (door telnet) en dit eindigde de container. Netcat heeft ook een '-k' persistente optie maar dat werkte niet, het is een bekend probleem. Er schijnt een betere versie te zijn genaamd ncat maar die is niet beschikbaar in het Busybox image.
Daarom gebruik ik het httpd commando:
httpd -f -v -p 1234
Samenvattend, in de database container gebruiken we httpd als de luisterende service.
Applicatie container
Helaas is curl niet beschikbaar in de Busybox image en het wget commando in Busybox ondersteunt geen andere poorten dan 80. Daarom gebruik ik telnet in de applicatie container om verbinding te maken met de httpd server.
Tenslotte gebruik ik netstat om de luisterpoorten in de containers te controleren.
De twee docker-compose bestanden
Het database docker-compose bestand, db.yml
In de database container maken we het netwerk 'postgres12_network' aan.
# db.yml
version: '3.7'
services:
postgres12:
image: busybox
container_name: postgres12_container
command: /bin/httpd -f -v -p 1234
networks:
- default
networks:
default:
name: postgres12_network
De toepassing docker-compose bestand, app.yml
In de applicatie container consumeren we het netwerk 'postgres12_network'.
# app.yml
version: '3.7'
services:
app:
image: busybox
container_name: app_container
command: sleep infinity
networks:
- default
- postgres
networks:
postgres:
external:
name: postgres12_network
Testen van de database container
Wees voorbereid, we gebruiken hier veel terminal vensters.
Open een terminal venster, en start de database container:
docker-compose -f db.yml up
Om te controleren of de container opgestart is, open een ander terminal venster en type:
docker ps
Resultaat:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4ab28dc6d47b busybox "/bin/httpd -f -v -p…" 19 minutes ago Up 19 minutes postgres12_container
Om te controleren of het Docker netwerk is aangemaakt, type:
docker network ls
Resultaat:
NETWORK ID NAME DRIVER SCOPE
539decc283dd postgres12_network bridge local
In een derde terminal venster gaan we de database container binnen, met behulp van exec, en starten een shell (sh) sessie:
docker-compose -f db.yml exec postgres12 /bin/sh
Controleer of de httpd deamon luistert naar poort 1234:
netstat -l -t
Resultaat:
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 localhost:41825 0.0.0.0:* LISTEN
tcp 0 0 :::1234 :::* LISTEN
Maak nu verbinding met de httpd deamon:
telnet postgres12 1234
Resultaat:
Connected to postgres12
In telnet, druk op <ENTER> of typ iets anders en druk op <ENTER>.
Resultaat:
HTTP/1.1 408 Request Timeout
Date: Wed, 26 May 2021 11:42:22 GMT
Connection: close
Content-type: text/html
<HTML><HEAD><TITLE>408 Request Timeout</TITLE></HEAD>
<BODY><H1>408 Request Timeout</H1>
No request appeared within 60 seconds
</BODY></HTML>
Connection closed by foreign host
Het ziet er misschien slecht uit maar het ziet er in feite goed uit, we kregen een antwoord van de httpd deamon!
In het eerste terminal venster zou er een bericht moeten staan zoals:
postgres12_container | [::ffff:192.168.48.2]:33264: response:400
Als je telnet probeert met een andere poort, zal de boodschap zijn:
telnet: can't connect to remote host (192.168.48.2): Connection refused
So far so good, laten we verder gaan met de applicatie container.
Testen van de applicatie container
Open een terminal venster, en start de applicatie container:
docker-compose -f app.yml up
In een ander terminal venster controleer of de container opgestart is, type:
docker ps
Resultaat:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9df4c69b8772 busybox "sleep infinity" 58 seconds ago Up 57 seconds app_container
4ab28dc6d47b busybox "/bin/httpd -f -v -p…" 42 minutes ago Up 42 minutes postgres12_container
Beide containers zijn nu up and running.
In een ander terminal venster gaan we de applicatie container binnen, met exec, en starten een shell (sh) sessie:
docker-compose -f app.yml exec app /bin/sh
Controleer of we verbinding kunnen maken met de httpd deamon in de database container:
telnet postgres12 1234
Resultaat:
Connected to postgres12
Dat is goed, alles werkt zoals verwacht.
Samenvatting
Het is grappig (NOT) dat de vraag + beantwoordt over hoe twee Docker containers te verbinden een enorme hoeveelheid stemmen heeft op Stack Overflow, zie onderstaande links. Ik denk dat de documentatie op de Docker website een stuk verbeterd is, maar het heeft meer (triviale) voorbeelden nodig. De 'name' optie in de netwerken sectie maakt het eenvoudiger om netwerken te definiëren en te lezen wat er in een docker-compose bestand gebeurt.
Tenslotte, Busybox is een klein plaatje maar ook erg beperkt. Het zou leuk zijn als er meer netwerk commando's aan toegevoegd zouden worden.
Links / credits
BusyBox - The Swiss Army Knife of Embedded Linux
https://www.busybox.net/downloads/BusyBox.html
Communication between multiple docker-compose projects
https://stackoverflow.com/questions/38088279/communication-between-multiple-docker-compose-projects/38089080#38089080
netcat - keep listening for connection in Debian
https://superuser.com/questions/1008348/netcat-keep-listening-for-connection-in-debian
Networking in Compose
https://docs.docker.com/compose/networking/
Lees meer
Docker Docker-compose
Recent
- Database UUID primaire sleutels van je webapplicatie verbergen
- Don't Repeat Yourself (DRY) met Jinja2
- SQLAlchemy, PostgreSQL, maximum aantal rijen per user
- Toon de waarden in SQLAlchemy dynamische filters
- Veilige gegevensoverdracht met Public Key versleuteling en pyNaCl
- rqlite: een alternatief voor SQLite met hoge beschikbaarheid en distributed
Meest bekeken
- Met behulp van Python's pyOpenSSL om SSL-certificaten die van een host zijn gedownload te controleren
- Gebruik van UUIDs in plaats van Integer Autoincrement Primary Keys met SQLAlchemy en MariaDb
- Maak verbinding met een dienst op een Docker host vanaf een Docker container
- PyInstaller en Cython gebruiken om een Python executable te maken
- SQLAlchemy: Gebruik van Cascade Deletes om verwante objecten te verwijderen
- Flask RESTful API verzoekparametervalidatie met Marshmallow-schema's