wake-up-neo.com

Der Rails-Server wird noch in einem neuen geöffneten Docker-Container ausgeführt

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 | => RunRails 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

31
handkock

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.

44
TopperH

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.

35

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!

5
charlesdg

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

2
mrpepo877

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)

  1. 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. 

  2. 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

2
Dan Key

Dies ist eine angepasste Version von Brendon Whateleys ???? answer für

Docker Compose Solution

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

????

1
davegson

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.

0
Jimmy M.G. Lim

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.

0
Sheetal Kaul