Ich möchte mein Rails-Projekt mit Docker bereitstellen. Also benutze ich Docker-Compose. Ich bekomme aber eine seltsame Fehlermeldung. Beim Ausführen von docker-compose up (dieser enthält db-container mit postgresql, redis und web container mit Rails) bekomme ich eine
web_1 | => Booting Puma
web_1 | => Rails 4.2.4 application starting in production on http://0.0.0.0:3000
web_1 | => Run
Rails server -hfor more startup options
web_1 | => Ctrl-C to shutdown server
web_1 | A server is already running. Check /usr/src/app/tmp/pids/server.pid.
web_1 | Exiting
So Ich kann nicht verstehen, warum ich diese Meldung erhalte, da jedes Mal, wenn ich Docker-Compose ausführte, neue Container beginnen, nicht die vorherigen. Selbst wenn Sie diese server.pid
löschen möchten, kann ich das nicht, weil dieser Container nicht läuft.
meine docker-compose.yml-Datei
web:
dockerfile: Dockerfile-Rails
build: .
command: bundle exec Rails s -p 3000 -b '0.0.0.0'
ports:
- "80:3000"
links:
- redis
- db
environment:
- REDISTOGO_URL=redis://[email protected]:6379/
redis:
image: redis
db:
dockerfile: Dockerfile-db
build: .
env_file: .env_db
Dockerfile-Rails
FROM Rails:onbuild
ENV Rails_ENV=production
Ich glaube nicht, dass ich alle meine Dockerfiles veröffentlichen muss
UPD: Ich habe es selbst behoben: Ich habe gerade alle meine Container gelöscht und den docker-compose up
noch einmal ausgeführt
Sie verwenden ein Onbuild-Image, sodass Ihr Arbeitsverzeichnis in das Container-Image eingebunden ist. Dies ist sehr gut für die Entwicklung, da Ihre App in Echtzeit aktualisiert wird, wenn Sie Ihren Code bearbeiten, und Ihr Host-System beispielsweise aktualisiert wird, wenn Sie eine Migration ausführen.
Dies bedeutet auch, dass das tmp-Verzeichnis des Host-Systems jedes Mal, wenn ein Server ausgeführt wird, mit der PID-Datei geschrieben wird und dort bleibt, wenn der Server nicht ordnungsgemäß heruntergefahren wird.
Führen Sie einfach diesen Befehl von Ihrem Host-System aus:
Sudo rm tmp/pids/server.pid
Dies kann sehr schmerzhaft sein, wenn Sie beispielsweise einen Vorarbeiter unter Docker-Compose verwenden, da durch das Drücken von Strg + C die PID-Datei nicht entfernt wird.
Ich war über das gleiche Problem für eine Weile verblüfft, bis ich herausgefunden hatte, was wirklich vor sich ging. Die eigentliche Antwort ist weiter unten ... Zunächst möchten Sie vielleicht den folgenden Befehl in Ihrer Datei docker-compose.yml ausprobieren:
command: /bin/sh -c "rm -f /Rails/tmp/pids/server.pid && Rails server puma"
(Ich verwende Alpine und busybox, um die Dinge winzig zu halten, also keine Bash! Aber die Option -c funktioniert auch mit Bash.) Dadurch wird die Datei gelöscht, wenn sie existiert, damit Sie nicht mit dem Problem festhalten, das der Container enthält Beenden und sitzen dort nicht in der Lage, Befehle auszuführen.
Leider ist dies NICHT eine gute Lösung, da Sie vor dem Server eine zusätzliche Ebene von/bin/sh hinzufügen und dies verhindert, dass der Server den Befehl stop erhält. Das Ergebnis ist, dass die Docker-Stopp-Befehle keinen ordnungsgemäßen Abbruch bewirken und das Problem immer auftreten wird.
Sie können den Befehl rm einfach mit docker-compose ausführen, um die Datei zu entfernen und den Befehl anschließend wieder auf den Server zu ändern und fortzufahren.
Die eigentliche Antwort ist jedoch das Erstellen einer einfachen docker-entry.sh -Datei, und stellen Sie sicher, dass Sie sie mit dem Ausführungsformular Entrypoint Documentation aufrufen, damit Signale (wie stop) zum Serverprozess gelangen.
#!/bin/sh
set -e
if [ -f tmp/pids/server.pid ]; then
rm tmp/pids/server.pid
fi
exec bundle exec "[email protected]"
HINWEIS: Wir verwenden exec in der letzten Zeile, um sicherzustellen, dass Rails als PID 1 (d. H. Keine zusätzliche Shell) ausgeführt wird, und die Signale werden gestoppt. Fügen Sie dann in der Datei Dockerfile (oder der Datei compose.yml) den Entrypoint und den Befehl hinzu
# Get stuff running
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["Rails", "server", "puma"]
Und wieder MÜSSEN Sie das [] -Format verwenden, so dass es ausgeführt wird, anstatt als sh -c "" ausgeführt zu werden.
Was ich getan habe, ist die bash Shell von Docker:
docker-compose run web /bin/bash
entfernen Sie dann die folgende Datei
rm tmp/pids/server.pid
Hoffe, dass es hilft!
für meine Arbeit:
docker-compose run web bash
und dann Ordner für Ordner mit dem Befehl cd gehen (ich verwende Win 7 Toolbox)
rm tmp/pids/server.pid
Für diejenigen, die Probleme haben, wenn es keinen tmp/pids/server.pid
gibt, gibt es tatsächlich:
(Docker Version 1.11.2, Build b9f10c9)
Eine Lösung, die für mich funktioniert hat, ist, docker-compose.yml
einen exakten Befehl hinzuzufügen, zum Beispiel:
command:
Rails s -b0
Mit diesem Befehl, der in der Tat einfach die CMD von Dockerfile duplizieren kann - Problem mit veraltetem .pid
wird nicht angezeigt.
Eine andere Option, wenn Sie die CMD von Dockerfile verwenden müssen, ist die Ausführung mit der Option --build
, um das Image wiederherzustellen:
docker-compose up --build
Obwohl es Zeit braucht, ist die erste Lösung bequemer
Dies ist eine angepasste Version von Brendon Whateleys ???? answer für
1. docker-entrypoint.sh erstellen
#!/bin/bash
set -e
if [ -f tmp/pids/server.pid ]; then
rm tmp/pids/server.pid
fi
exec bundle exec "[email protected]"
2. Passen Sie Ihre Docker-Compose.yml an
services:
web:
build: .
entrypoint: /myapp/docker-entrypoint.sh
command: ["Rails", "server", "-b", "0.0.0.0"]
volumes:
- .:/myapp
ports:
- "3000:3000"
Beachten Sie, dass Sie den Pfad angeben müssen, an dem Sie Ihre App gemountet haben, z. B. /myapp
.
2.5 Wenn ein Berechtigungsfehler auftritt
Führen Sie dies in Ihrem Terminal aus, bevor Siedocker-compose up
ausführen oder Ihr Image erstellen. Vielen Dank sajadghawami .
chmod +x docker-entrypoint.sh
3. Du musst server.pid nie wieder manuell entfernen
????
In Ihrer Datei docker-compose.yml können Sie unter dem Anwendungscontainer selbst Folgendes verwenden:
befehl: ["rm /your-app-path/tmp/pids/server.pid && Bündel exec bin/Rails s -p 3000 -b '0.0.0.0'"]
oder
befehl: ["rm /your-app-path/tmp/pids/server.pid; Vorarbeiterstart"]
der Grund für entweder ";" oder "&&" bedeutet, dass letzteres ein Exit-Signal sendet, wenn rm die Datei nicht finden kann, wodurch der Container vorzeitig angehalten wird. Der Prior wird weiter ausgeführt.
Warum wird das überhaupt verursacht? Das Vernünftige ist, wenn der Server (puma/thin/was auch immer) nicht sauber beendet wird, wird eine PID auf dem Host-Computer zurückbleiben, die einen Exit-Fehler verursacht.
Wenn Sie sich abenteuerlustig fühlen, können Sie in der Codebase nach server.pid suchen und prüfen, wo die PID geschrieben wird. Auf diese Weise können Sie prüfen, ob das Schreibproblem nicht behoben werden kann. Denn scheinbar hilft die PID-Erstellung, doppelte Dienste in zwei verschiedenen Docker-Containern auszuführen. Aber das sollte im Docker so sein, wie es ist. Wenn dies aus irgendeinem Grund nicht der Fall ist, sollte dies auf jeden Fall durch die Port-Kollisionsmethodik behoben werden. Hinweis: Ich habe diesen Ansatz noch nicht ausprobiert, da sich das System im Allgemeinen bewegt :)
Alternativ können Sie Befehle in Ihrem Makefile haben. Wo die Aufgabe dies tut:
aufgabe:
Docker-Compose-Stop Dienstname
docker-compose rm service_name
rm -f ./tmp/pids/server.pid (oder relativer Pfadname Ihrer PID-Datei)
docker-compose up service_name
Und dann vrooom make task
im Terminal und drücken Sie die Eingabetaste .. Die obigen Taskbefehle setzen voraus, dass der Dienst, den Sie ausführen möchten, in einer Datei namens docker-compose.yml enthalten ist
Wenn der Name anders ist, dann der Befehl
docker-compose stop service_name -> docker-compose -f Ihr-Compose-Dateiname.yml stop service_name
und so weiter und so fort.
=====================.... Zurückgekommen, um dies zu aktualisieren. Also habe ich versucht, meine write_pid-Methodenfunktionalität zu kommentieren. Behalten Sie grundsätzlich die Methodendefinition bei, aber lassen Sie sie nichts tun. Es funktioniert soweit gut. Es schreibt die PID überhaupt nicht. Wenn Sie Ihre Dienste in Docker ausführen, ist dies meiner Meinung nach absolut sicher.