
Als ich Autofahren lernte, ist mein Fahrlehrer gleich in der ersten Stunde rückwärts an eine Kreuzung gefahren und hat dann gesagt, dass man das auf keinen Fall machen darf – niemals. Diese Regel habe ich sofort und fürs Leben gelernt.
Wenn man Kindern "Schädliche Tipps" von Grigori Oster vorliest, sieht man, wie leicht und unbeschwert sie verstehen, dass man so etwas nicht tun sollte.
Es gibt eine Menge Artikel darüber, wie man ein Dockerfile richtig schreibt. Aber ich habe keine Anleitungen gefunden, wie man ein falsches Dockerfile schreibt. Ich schließe diese Lücke. Und vielleicht wird es weniger solcher Dockerfiles in den Projekten geben, die ich unterstütze.
Alle Charaktere, Situationen und Dockerfiles sind fiktiv. Wenn Sie sich erkannt haben, tut mir leid.
Erstellen wir ein Dockerfile, furchtbar und schrecklich
Peter (Senior Java/Ruby/PHP-Entwickler): Kollege Wladimir, hast du das neue Modul schon in Docker hochgeladen?
Wladimir (Junior): Nein, ich hatte keine Zeit, ich komme mit Docker einfach nicht klar. So viele Artikel, dass mir ganz schwindelig wird.
Peter: Unsere Frist ist schon vor einem Jahr abgelaufen. Lass mich helfen, wir klären das währenddessen. Erzähl mir, was bei dir nicht funktioniert.
Wladimir: Ich kann kein Basissystem auswählen, ich möchte ein minimales, aber alles Wichtige muss da sein.
Peter: Nimm das Ubuntu-Image, darin ist alles, was du brauchst. Das, was überflüssig ist, könnte später nützlich sein. Und vergiss nicht, den Tag 'latest' zu setzen, damit es immer die neueste Version ist.
Und in der Dockerfile erscheint die erste Zeile:
FROM ubuntu:latestPeter: Was kommt als nächstes, womit haben wir unser Modul geschrieben?
Wassilij: Mit Ruby, da muss ein Webserver und ein paar Dienstprozesse laufen.
Peter: Aha, was wir brauchen: Ruby, Bundler, Node.js, ImageMagick und was da sonst noch … Und außerdem, mach ein Upgrade, um sicher die neuesten Pakete zu bekommen.
Wassilij: Sollen wir keinen Benutzer anlegen, damit wir nicht als root arbeiten?
Peter: Lass das, das ist später nur ein weiteres Problem mit den Rechten.
Wassilij: Ich brauche ein wenig Zeit, etwa 15 Minuten, um das alles in einen Befehl zu packen. Ich habe gelesen, dass…
(Peter unterbricht den übergenauen und sehr cleveren Junior grob.)
Peter: Schreib es in einzelnen Befehlen, so lässt es sich einfacher lesen.
Die Dockerfile wächst:
FROM ubuntu:latest
RUN apt-get update
RUN apt-get upgrade
RUN apt-get -y install libpq-dev imagemagick gsfonts ruby-full
RUN gem install bundler
RUN curl -sL https://deb.nodesource.com/setup_9.x | sudo bash -
RUN apt-get install -y nodejs
RUN bundle install --without development test --path vendor/bundle
RUN rm -rf /usr/local/bundle/cache/*.gem
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*Hier stürmt Igor Ivanovitch, DevOps (aber mehr Ops als Dev), in den Raum und schreit:
KI: Peter, deine Entwickler haben die Produktionsdatenbank schon wieder kaputtgemacht. Wann hört das endlich auf…
Nach einem kleinen Wortgefecht beruhigt sich Igor Ivanovich und fragt nach, was die Kollegen hier gerade tun.
KI: Womit sind Sie beschäftigt?
Wasilij: Peter hilft mir, ein Dockerfile für das neue Modul zu erstellen.
KI: Lass mich mal sehen… Was habt ihr denn hier geschrieben? Ihr reinigt das Repository doch mit einem eigenen Befehl, das ist doch eine zusätzliche Ebene… Wie stellt ihr die Abhängigkeiten ein, wenn ihr die Gemfile nicht kopiert habt! Das ist alles nicht akzeptabel.
Peter: Gehen Sie bitte Ihren eigenen Angelegenheiten nach, wir kriegen das hier schon irgendwie hin.
Igor Ivanovich seufzt bedrückt und geht herauszufinden, wer die Datenbank kaputtgemacht hat.
Peter: Ja, aber er hat bezüglich des Codes recht, wir sollten ihn ins Image packen. Und lass uns gleich SSH und Supervisor installieren, wie sollen wir sonst die Prozesse starten?
Wasilij: Ich kopiere zuerst die Gemfile und die Gemfile.lock, installiere dann alles und kopiere danach das gesamte Projekt. Wenn sich die Gemfile nicht ändert, wird die Schicht aus dem Cache übernommen.
Peter: Was habt ihr alle mit diesen Schichten? Kopiere sofort alles. Sofort kopieren. In der ersten Zeile.
Das Dockerfile sieht jetzt so aus:
VON ubuntu:latest
COPY ./ /app
WORKDIR /app
RUN apt-get update
RUN apt-get upgrade
RUN apt-get -y install libpq-dev imagemagick gsfonts ruby-full ssh supervisor
RUN gem install bundler
RUN curl -sL https://deb.nodesource.com/setup_9.x | sudo bash -
RUN apt-get install -y nodejs
RUN bundle install --without development test --path vendor/bundle
RUN rm -rf /usr/local/bundle/cache/*.gem
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* Peter: Und, was kommt jetzt? Hast du die Konfigurationen für den Supervisor?
Wasilij: Nein, habe ich nicht. Aber ich mache es schnell.
Peter: Mach es später. Lass uns jetzt das Init-Skript skizzieren, das alles starten wird. Also, du startest ssh mit nohup, damit wir uns mit dem Container verbinden und sehen können, was schiefgelaufen ist. Dann startest du auch den Supervisor. Und schließlich startest du einfach den Passenger.
W: Aber ich habe gelesen, dass es einen Prozess geben sollte, damit Docker weiß, dass etwas schiefgelaufen ist und den Container neu starten kann.
P: Mach dir keine Gedanken über so einen Blödsinn. Und überhaupt, wie? Wie wirst du das alles in einem Prozess starten? Lass Igor Ivanovich sich um die Stabilität kümmern, er wird schließlich dafür bezahlt. Unsere Aufgabe ist es, Code zu schreiben. Und er sollte dankbar sein, dass wir ihm das Dockerfile geschrieben haben.
Zehn Minuten später und zwei Videos über Katzen.
W: Ich habe alles gemacht. Ich habe auch ein paar Kommentare hinzugefügt.
P: Zeig her!
Aktuelle Version des Dockerfile:
FROM ubuntu:latest
# Kopieren Sie den Quellcode
COPY ./ /app
WORKDIR /app
# Aktualisieren Sie die Paketliste
RUN apt-get update
# Pakete aktualisieren
RUN apt-get upgrade
# Benötigte Pakete installieren
RUN apt-get -y install libpq-dev imagemagick gsfonts ruby-full ssh supervisor
# Bundler installieren
RUN gem install bundler
# Node.js installieren, das für das Bauen von Statischen Inhalten verwendet wird
RUN curl -sL https://deb.nodesource.com/setup_9.x | sudo bash -
RUN apt-get install -y nodejs
# Abhängigkeiten installieren
RUN bundle install --without development test --path vendor/bundle
# Caches aufräumen
RUN rm -rf /usr/local/bundle/cache/*.gem
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# Führen Sie ein Skript beim Starten des Containers aus, das alles andere starten wird.
CMD ["/app/init.sh"]P: Das ist großartig, ich mag es. Und die Kommentare auf Russisch sind praktisch und leserlich, jeder sollte so arbeiten. Ich habe dir alles beigebracht, du kannst jetzt selbst weitermachen. Lass uns einen Kaffee trinken...
Nun, da haben wir die perfekt schreckliche Dockerfile, bei deren Anblick Igor Ivanovich kündigen möchte und seine Augen noch eine Woche schmerzen werden. Die Dockerfile hätte natürlich noch schlimmer sein können, es gibt keine Grenze für die Perfektion. Aber für den Anfang ist das schon in Ordnung.
Ich möchte abschließend mit einem Zitat von Grigori Oster enden:
Wenn Sie sich noch nicht sicher sind,
Welchen Weg Sie im Leben gewählt haben,
Und nicht wissen, wo Sie anfangen sollen,
Ihren Arbeitsweg zu beginnen,
Schlagen Sie die Glühbirnen in den Treppenhäusern ein —
Die Leute werden Ihnen „Danke“ sagen.
Sie helfen den Menschen,
Strom zu sparen.
Quelle: habr.com
