Ich habe eine compose-Datei mit v3, bei der 3 Dienste das gleiche Volume gemeinsam nutzen/verwenden. Während des Swarm-Modus müssen zusätzliche Container und Volumes erstellt werden, um unsere Dienste im gesamten Cluster zu verwalten.
Ich plane die Verwendung eines NFS-Servers, damit eine einzelne NFS-Freigabe direkt auf allen Hosts im Cluster bereitgestellt wird.
Ich habe unten zwei Möglichkeiten gefunden, aber es müssen zusätzliche Schritte auf dem Docker-Host ausgeführt werden.
Stellen Sie die NFS-Freigabe mit dem Befehl "fstab" oder "mount" auf dem Host bereit und verwenden Sie sie als Host-Volume für Andockdienste.
Verwenden Sie das Netshare-Plugin - https://github.com/ContainX/docker-volume-netshare
Gibt es eine Standardmethode, mit der ich NFS-Freigaben mit Docker Compose v3 direkt verwenden/bereitstellen kann, indem ich nur wenige/keine Schritte auf dem Docker-Host durchführe.
Nachdem Sie festgestellt haben, dass dies massiv undokumentiert ist, können Sie ein NFS-Volume mithilfe von Stack- und Docker-Composition mounten.
Das Wichtigste ist, dass Sie version: "3.2"
oder höher verwenden müssen. Wenn Sie dies nicht tun, werden Sie seltsame und nicht offensichtliche Fehler haben.
Das zweite Problem ist, dass Volumes nicht automatisch aktualisiert werden, wenn sich ihre Definition ändert. Dies kann dazu führen, dass Sie ein Kaninchenloch der Meinung sind, dass Ihre Änderungen nicht korrekt sind, wenn sie nicht angewendet wurden. Stellen Sie sicher, dass docker rm VOLUMENAME
überall vorhanden ist, da das Volume vorhanden ist und nicht validiert wird.
Das dritte Problem ist eher ein NFS-Problem - Der NFS-Ordner wird nicht erstellt auf dem Server, wenn er nicht existiert. Genau so funktioniert NFS. Sie müssen sicherstellen, dass es existiert, bevor Sie etwas tun.
(Entfernen Sie "soft" und "nolock" nur, wenn Sie sicher sind, dass Sie wissen, was Sie tun. Andernfalls kann das Andockfenster nicht einfrieren, wenn der NFS-Server nicht mehr funktioniert.)
Hier ist ein vollständiges Beispiel:
[[email protected] docker-mirror]# cat nfs-compose.yml
version: "3.2"
services:
rsyslog:
image: jumanjiman/rsyslog
ports:
- "514:514"
- "514:514/udp"
volumes:
- type: volume
source: example
target: /nfs
volume:
nocopy: true
volumes:
example:
driver_opts:
type: "nfs"
o: "addr=10.40.0.199,nolock,soft,rw"
device: ":/docker/example"
[[email protected] docker-mirror]# docker stack deploy --with-registry-auth -c nfs-compose.yml rsyslog
Creating network rsyslog_default
Creating service rsyslog_rsyslog
[[email protected] docker-mirror]# docker stack ps rsyslog
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
tb1dod43fe4c rsyslog_rsyslog.1 jumanjiman/rsyslog:latest swarm-4 Running Starting less than a second ago
[[email protected] docker-mirror]#
Nun zu Swarm-4:
[email protected]:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d883e0f14d3f jumanjiman/rsyslog:latest "rsyslogd -n -f /e..." 6 seconds ago Up 5 seconds 514/tcp, 514/udp rsyslog_rsyslog.1.tb1dod43fe4cy3j5vzsy7pgv5
[email protected]:~# docker exec -it d883e0f14d3f df -h /nfs
Filesystem Size Used Available Use% Mounted on
:/docker/example 7.2T 5.5T 1.7T 77% /nfs
[email protected]:~#
Dieses Volume wird auf jedem Schwarmknoten erstellt ( aber nicht zerstört ), auf dem der Stack ausgeführt wird.
[email protected]:~# docker volume inspect rsyslog_example
[
{
"CreatedAt": "2017-09-29T13:53:59+10:00",
"Driver": "local",
"Labels": {
"com.docker.stack.namespace": "rsyslog"
},
"Mountpoint": "/var/lib/docker/volumes/rsyslog_example/_data",
"Name": "rsyslog_example",
"Options": {
"device": ":/docker/example",
"o": "addr=10.40.0.199,nolock,soft,rw",
"type": "nfs"
},
"Scope": "local"
}
]
[email protected]:~#
Ja, Sie können direkt auf ein NFS aus der Erstellungsdatei verweisen:
volumes:
db-data:
driver: local
driver_opts:
type: nfs
o: addr=$SOMEIP,rw
device: ":$PathOnServer"
Auf analoge Weise können Sie auf jedem Host ein nfs-Volume erstellen.
docker volume create --driver local --opt type=nfs --opt o=addr=$SomeIP,rw --opt device=:$DevicePath --name nfs-docker
Abhängig davon, wie ich das Volume verwenden muss, habe ich die folgenden 3 Optionen.
Zunächst können Sie das benannte Volume direkt erstellen und als externes Volume in compose oder als benanntes Volume in einem Befehl docker run
Oder docker service create
Verwenden.
# create a reusable volume
$ docker volume create --driver local \
--opt type=nfs \
--opt o=nfsvers=4,addr=nfs.example.com,rw \
--opt device=:/path/to/dir \
foo
Als nächstes gibt es die Syntax --mount
, Die mit docker run
Und docker service create
Funktioniert. Dies ist eine ziemlich lange Option. Wenn Sie eine durch Kommas getrennte Option in eine andere durch Kommas getrennte Option einbetten, müssen Sie dem ausgeführten Befehl einige Anführungszeichen (mit Escape-Zeichen, damit die Shell sie nicht entfernt) übergeben. Ich verwende dies in der Regel für einen einmaligen Container, der auf NFS zugreifen muss (z. B. einen Utility-Container zum Einrichten von NFS-Verzeichnissen):
# or from the docker run command
$ docker run -it --rm \
--mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=nfs,\"volume-opt=o=nfsvers=4,addr=nfs.example.com\",volume-opt=device=:/Host/path \
foo
# or to create a service
$ docker service create \
--mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=nfs,\"volume-opt=o=nfsvers=4,addr=nfs.example.com\",volume-opt=device=:/Host/path \
foo
Zuletzt können Sie das benannte Volume in Ihrer Compose-Datei definieren. Ein wichtiger Hinweis dabei ist, dass das Namensvolumen nur einmal erstellt und nicht mit Änderungen aktualisiert wird. Wenn Sie also das benannte Volume ändern müssen, möchten Sie ihm einen neuen Namen geben.
# inside a docker-compose file
...
services:
example-app:
volumes:
- "nfs-data:/data"
...
volumes:
nfs-data:
driver: local
driver_opts:
type: nfs
o: nfsvers=4,addr=nfs.example.com,rw
device: ":/path/to/dir"
...
In jedem dieser Beispiele:
nfs
gesetzt, nicht auf nfs4
. Dies liegt daran, dass Docker einige nützliche Funktionen für das Feld addr
bietet, jedoch nur für den Typ nfs
.o
sind die Optionen, die an den Mount-Systemaufruf übergeben werden. Ein Unterschied zwischen dem Befehl mount syscall und mount unter Linux besteht darin, dass das Gerät den Teil vor dem Verschieben von :
In eine Option addr
hat.nfsvers
wird verwendet, um die NFS-Version festzulegen. Dies vermeidet Verzögerungen, da das Betriebssystem zuerst andere NFS-Versionen versucht.addr
kann ein DNS-Name sein, wenn Sie type=nfs
verwenden, und nicht nur eine IP-Adresse. Sehr nützlich, wenn Sie mehrere VPCs mit unterschiedlichen NFS-Servern haben, die denselben DNS-Namen verwenden, oder wenn Sie den NFS-Server in Zukunft anpassen möchten, ohne jedes Volume-Mount zu aktualisieren.rw
(Lese-/Schreibzugriff) können an die Option o
übergeben werden.device
ist der Pfad auf dem Remote-NFS-Server. Der führende Doppelpunkt ist erforderlich. Dies ist ein Artefakt dafür, wie der Befehl mount die IP-Adresse in das Feld addr
für den Systemaufruf verschiebt. Dieses Verzeichnis muss auf dem Remote-Host vorhanden sein, bevor das Volume in einem Container bereitgestellt wird.--mount
Ist das Feld dst
der Pfad innerhalb des Containers. Für benannte Volumes legen Sie diesen Pfad auf der rechten Seite des Volume-Mounts (in der kurzen Syntax) in Ihrem Befehl docker run -v
Fest.Wenn Sie Berechtigungsprobleme beim Zugriff auf ein Remote-NFS-Volume haben, ist eine häufige Ursache, dass Container als Root ausgeführt werden und der NFS-Server auf Root-Squash eingestellt ist (wodurch der gesamte Root-Zugriff auf den Benutzer nobody geändert wird). Sie müssen Ihre Container entweder so konfigurieren, dass sie als bekannte Nicht-Root-UID ausgeführt werden, die Zugriff auf die Verzeichnisse auf dem NFS-Server hat, oder Root-Squash auf dem NFS-Server deaktivieren.
Meine Lösung für AWS EFS, die funktioniert:
Installieren Sie das nfs-common-Paket:
Sudo apt-get install -y nfs-common
Überprüfen Sie, ob Ihr EFS funktioniert:
mkdir efs-test-point Sudo chmod go + rw efs-test-point
Sudo mount -t nfs -o nfsvers = 4.1, rsize = 1048576, wsize = 1048576, hard, timeo = 600, retrans = 2, noresvport [YOUR_EFS_DNS]:/efs-test-point
berühren Sie efs-testpoint/1.txt Sudo umount efs-testpoint / ls -la efs-testpoint /
das Verzeichnis muss leer sein
Sudo mount -t nfs -o nfsvers = 4.1, rsize = 1048576, wsize = 1048576, hard, timeo = 600, retrans = 2, noresvport [YOUR_EFS_DNS]:/efs-test-point
ls -la efs-test-point/
datei 1.txt muss vorhanden sein
Konfigurieren Sie die Datei docker-compose.yml:
dienstleistungen: sidekiq: Bände: - uploads_tmp_efs:/home/application/public/uploads/tmp ... Bände: uploads_tmp_efs: Treiber: lokal driver_opts: Typ: nfs o: addr = [YOUR_EFS_DNS], nfsvers = 4.1, rsize = 1048576, wsize = 1048576, hart, timeo = 600, retrans = 2 Gerät: [YOUR_EFS_DNS]: /
Mein Problem wurde mit dem Ändern des Treiberoptionstyps auf NFS4 behoben.
volumes:
my-nfs-share:
driver: local
driver_opts:
type: "nfs4"
o: "addr=172.24.0.107,rw"
device: ":/mnt/sharedwordpress"