
Als ich das Autofahren lernte, fuhr der Fahrlehrer bereits in der ersten Stunde rückwärts in eine Kreuzung und sagte dann, dass man das niemals tun darf – überhaupt nicht. Diese Regel habe ich sofort und für mein ganzes Leben behalten.
Wenn du den Kindern "Schädliche Ratschläge" von Grigori Oster vorliest, siehst du, wie leicht es ihnen fällt zu verstehen, dass man das nicht tun sollte.
Es gibt eine Menge Artikel darüber, wie man ein Dockerfile richtig schreibt. Aber ich habe keine Anleitungen gefunden, wie man falsche Dockerfiles schreibt. Ich fülle diese Lücke. Vielleicht wird es in den Projekten, die ich betreue, weniger solcher Dockerfiles geben.
Alle Figuren, Situationen und Dockerfiles sind erfunden. Wenn du dich erkannt hast, tut mir leid.
Erstellen wir ein Dockerfile, teuflisch und schrecklich
Petr (Senior Java/Ruby/PHP-Entwickler): Kollege Wasilij, hast du das neue Modul bereits in Docker hochgeladen?
Wasilij (Junior): Nein, ich habe es nicht geschafft, ich kann mit Docker einfach nicht umgehen. So viele Artikel darüber, meine Augen schwirren.
Petr: Unsere Frist ist vor einem Jahr abgelaufen. Lass mich helfen, wir klären das im Prozess. Erzähl, was bei dir nicht klappt.
Wasilij: Ich kann das Basis-Image nicht wählen, ich brauche eines, das minimal ist, aber alles Wichtige enthält.
Petr: Nimm das Ubuntu-Image, darin ist alles, was du brauchst. Und das Überflüssige braucht man später noch. Und vergiss nicht, das Tag "latest" zu setzen, damit du immer die neueste Version hast.
Und im Dockerfile erscheint die erste Zeile:
FROM ubuntu:latestPetr: Was kommt als nächstes, womit haben wir unser Modul geschrieben?
Wasilij: Doch Ruby, dort sollte ein Webserver und ein paar Dienst-Demons laufen.
Petr: Aha, was wir brauchen: Ruby, Bundler, NodeJS, ImageMagick und was da noch ist… Und mach gleich ein Upgrade, um sicher die neuen Pakete zu bekommen.
Wasilij: Wollen wir keinen Benutzer erstellen, damit es nicht unter root läuft?
Petr: Ach komm, damit müssen wir uns später nicht um die Rechte kümmern.
Wasilij: Ich brauche Zeit, etwa 15 Minuten, um das alles in einen Befehl zu packen, ich habe gelesen, dass...
(Petr unterbricht den hartnäckigen und übermäßig klugen Junior grob.)
Petr: Schreibe in einzelnen Kommandos, das liest sich dann einfacher.
Das 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 Ivanovich, DevOps (aber mehr Ops als Dev), ins Büro und schreit:
II: Petja, deine Entwickler haben die Produktionsdatenbank schon wieder kaputt gemacht, wann wird das endlich aufhören….
Nachdem Igor Ivanovich sich etwas beruhigt hat, beginnt er herauszufinden, womit die Kollegen hier beschäftigt sind.
AI: Womit beschäftigt ihr euch?
Wassili: Peter hilft mir, ein Dockerfile für das neue Modul zu erstellen.
AI: Lass mal sehen… Was habt ihr denn hier geschrieben, ihr reinigt das Repository doch mit einem separaten Befehl, das ist doch eine zusätzliche Schicht… Wie setzt ihr die Abhängigkeiten, wenn ihr die Gemfile nicht kopiert habt? Und überhaupt, das ist nicht akzeptabel.
Peter: Geht bitte euren eigenen Weg, wir kriegen das schon irgendwie hin.
Igor Ivanovich seufzt melancholisch und geht darauf los, um herauszufinden, wer die Datenbank kaputt gemacht hat.
Peter: Ja, aber er hat doch recht mit dem Code, wir müssen das ins Image packen. Lass uns gleich ssh und supervisor installieren, wie sollen wir sonst die Dienste starten?
Wassili: Ich werde zuerst die Gemfile und Gemfile.lock kopieren, dann alles installieren, und danach kopiere ich das gesamte Projekt. Wenn sich die Gemfile nicht ändert, wird die Schicht aus dem Cache genommen.
Peter: Was habt ihr nur mit diesen Schichten, kopiere gleich alles. Sofort alles kopieren. Mit der ersten Zeile.
Das Dockerfile sieht jetzt so aus:
FROM 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: Also, was kommt als Nächstes? Hast du die Konfigurationen für den Supervisor?
Wassili: Nein, habe ich nicht. Aber ich mache das schnell.
Peter: Mach das später. Lass uns jetzt ein init-Skript entwerfen, das alles startet. Also, du startest ssh mit nohup, damit wir uns mit dem Container verbinden und sehen können, was schiefgelaufen ist. Starte dann auch den Supervisor. Und danach kannst du einfach passenger starten.
W: Aber ich habe gelesen, dass es nur einen Prozess geben sollte, so weiß Docker, dass etwas schiefgegangen ist und kann den Container neu starten.
P: Lass dich nicht mit so einem Quatsch ablenken. Und wie? Wie willst du das alles in einem Prozess starten? Lass Igor Ivanovich sich um die Stabilität kümmern, schließlich bekommt er nicht umsonst sein Gehalt. Unsere Aufgabe ist es, Code zu schreiben. Und überhaupt, er kann sich glücklich schätzen, dass wir das Dockerfile für ihn geschrieben haben.
Nach 10 Minuten und zwei Katzenvideos.
W: Ich habe alles gemacht. Ich habe noch einige Kommentare hinzugefügt.
P: Zeig her!
Die aktuelle Version des Dockerfiles:
FROM ubuntu:latest
# Den Quellcode kopieren
COPY ./ /app
WORKDIR /app
# Paketliste aktualisieren
RUN apt-get update
# Pakete aktualisieren
RUN apt-get upgrade
# Notwendige Pakete installieren
RUN apt-get -y install libpq-dev imagemagick gsfonts ruby-full ssh supervisor
# Bundler installieren
RUN gem install bundler
# Node.js installieren, wird für den Aufbau von statischen Inhalten verwendet
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 bereinigen
RUN rm -rf /usr/local/bundle/cache/*.gem
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# Skript beim Start des Containers ausführen, das alles andere startet.
CMD ["/app/init.sh"]P: Großartig, gefällt mir. Und die Kommentare auf Russisch, bequem und leserlich, so sollte jeder arbeiten. Ich habe dir alles beigebracht, jetzt kannst du es selbst. Lass uns Kaffee trinken…
Nun, wir haben also eine perfekt schreckliche Dockerfile erhalten, bei deren Anblick Igor Ivanovich kündigen möchte und ihm noch eine Woche die Augen wehtun werden. Die Dockerfile hätte natürlich noch schlimmer sein können, die Vollkommenheit kennt keine Grenzen. Aber für den Anfang wird es schon so gehen.
Ich möchte mit einem Zitat von Grigori Oster abschließen:
Wenn Sie sich noch nicht sicher
Im Leben für einen Weg entschieden haben,
Und nicht wissen, wo Sie anfangen sollen,
Ihren Arbeitsweg zu beginnen,
Zerschlagen Sie Glühbirnen in den Eingängen –
Die Leute werden Ihnen "Danke" sagen.
Sie werden den Menschen helfen,
Strom zu sparen.
Quelle: habr.com
