So stellen Sie Go-Webanwendungen mit Docker bereit

So stellen Sie Go-Webanwendungen mit Docker bereit

Dieser Artikel stellt die Verwendung von Docker und Docker Compose zum Bereitstellen unserer Go-Webanwendung vor.

Warum brauchen wir Docker?

Der Hauptzweck der Verwendung von Docker ist die Containerisierung. Das heißt, wir stellen eine konsistente Umgebung für Ihre Anwendung bereit, unabhängig vom Host, auf dem sie ausgeführt wird.

Stellen Sie sich vor, Sie kennen das folgende Szenario: Sie haben Ihre Anwendung lokal entwickelt, sie hat wahrscheinlich viele abhängige Umgebungen oder Pakete und sogar strenge Anforderungen an die spezifischen Versionen der Abhängigkeiten. Wenn der Entwicklungsprozess abgeschlossen ist, möchten Sie die Anwendung auf dem Webserver bereitstellen. An diesem Punkt müssen Sie sicherstellen, dass alle Abhängigkeiten korrekt installiert sind und die exakt gleichen Versionen aufweisen, da die Anwendung sonst möglicherweise abstürzt und nicht ausgeführt wird. Wenn Sie die Anwendung auf einem anderen Webserver bereitstellen möchten, müssen Sie den Vorgang von Anfang an wiederholen. In diesem Szenario kommt Docker ins Spiel.

Für den Host, auf dem unsere Anwendung läuft, sei es ein Laptop oder ein Webserver, müssen wir lediglich eine Docker-Containerplattform ausführen. Von nun an müssen Sie sich keine Gedanken mehr darüber machen, ob Sie MacOS, Ubuntu, Arch oder ein anderes verwenden. Sie definieren Ihre Anwendung einmal und führen sie überall aus.

Beispiel für eine Docker-Bereitstellung

Vorbereiten des Codes

Hier werde ich anhand eines einfachen, mit der net/http-Bibliothek geschriebenen Codes als Beispiel erklären, wie Docker für die Bereitstellung verwendet wird, und anschließend einen etwas komplexeren Fall der Projektbereitstellung erläutern.

Paket Haupt

importieren (
 "fmt"
 "net/http"
)

Funktion main() {
 http.HandleFunc("/", hallo)
 server := &http.Server{
 Adresse: ":8888",
 }
 fmt.Println("Serverstart...")
 wenn err := server.ListenAndServe(); err != nil {
 fmt.Printf("Serverstart fehlgeschlagen, Fehler: %v\n", Fehler)
 }
}

Funktion hallo(w http.ResponseWriter, _ *http.Request) {
 w.Write([]byte("hallo liwenzhou.com!"))
}

Der obige Code stellt externe Dienste über Port 8888 bereit und gibt eine String-Antwort zurück: Hallo liwenzhou.com!.

Erstellen eines Docker-Image

Ein Image enthält alles, was zum Ausführen einer Anwendung erforderlich ist: den Code oder die Binärdateien, die Laufzeit, Abhängigkeiten und alle anderen erforderlichen Dateisystemobjekte.

Oder einfach ausgedrückt: Ein Image ist alles, was eine Anwendung definiert und zu ihrer Ausführung erforderlich ist.

Schreiben einer Docker-Datei

Um ein Docker-Image zu erstellen, müssen Sie die Schritte in der Konfigurationsdatei angeben. Standardmäßig heißt diese Datei normalerweise Dockerfile. (Sie können dieser Datei zwar einen beliebigen Namen geben, am besten verwenden Sie jedoch das Standard-Dockerfile.)

Jetzt beginnen wir mit dem Schreiben der Docker-Datei. Der spezifische Inhalt ist wie folgt:

Hinweis: Einige Schritte sind nicht eindeutig und können Ihren Anforderungen entsprechend geändert werden, z. B. Dateipfad, Name der endgültigen ausführbaren Datei usw.

VON golang:alpine

# Setzen Sie die notwendigen Umgebungsvariablen ENV GO111MODULE=on für unser Image \
 CGO_ENABLED=0 \
 GOOS=linux \
 GOARCH=amd64

# Wechseln Sie in das Arbeitsverzeichnis: /build
ARBEITSVERZEICHNIS /build

# Den Code in den Container COPY kopieren. .

# Kompilieren Sie unseren Code in eine binäre ausführbare Datei app
Führen Sie „go build -o app“ aus.

# Wechseln Sie in das Verzeichnis /dist zum Speichern der generierten Binärdateien WORKDIR /dist

# Kopieren Sie die Binärdateien aus dem Verzeichnis /build hierher RUN cp /build/app .

#Service-Port EXPOSE 8888 deklarieren

# Befehl, der beim Starten des Containers ausgeführt werden soll CMD ["/dist/app"]

Dockerfile-Analyse

Aus
Wir verwenden das Basisimage golang:alpine, um unser Image zu erstellen. Dies ist dasselbe Basis-Image, das wir erstellen werden und das in einem Docker-Repository gespeichert ist, auf das wir zugreifen können. Auf diesem Image läuft die Linux-Distribution Alpine. Diese ist klein und hat Go integriert, sodass sie für unseren Anwendungsfall gut geeignet ist. Es gibt eine große Anzahl öffentlich verfügbarer Docker-Images, siehe https://hub.docker.com/_/golang

Umgebung
Wird verwendet, um die Umgebungsvariablen festzulegen, die wir während der Kompilierungsphase benötigen.

ARBEITSVERZEICHNIS, KOPIEREN, AUSFÜHREN
Die Befehle werden in den Kommentaren erklärt, sodass sie leicht zu verstehen sind.

EXPORT,CMD
Abschließend deklarieren wir den Service-Port, da unsere Anwendung auf diesem Port lauscht und über diesen Port externe Dienste bereitstellt. Und wir definieren auch den Standardbefehl CMD ["/dist/app"], der ausgeführt wird, wenn wir das Image ausführen.

Erstellen des Images

Führen Sie im Projektverzeichnis den folgenden Befehl aus, um ein Image zu erstellen, und geben Sie den Image-Namen als goweb_app an:

Docker-Build. -t goweb_app

Warten Sie, bis der Build-Prozess abgeschlossen ist. Die folgende Eingabeaufforderung wird ausgegeben:

...
Erfolgreich erstellt 90d9283286b7
Erfolgreich getaggt mit goweb_app:latest

Jetzt ist unser Image fertig, aber es tut derzeit nichts. Als nächstes müssen wir unser Image ausführen, damit es unsere Anfragen verarbeiten kann. Ein laufendes Image wird als Container bezeichnet.

Führen Sie den folgenden Befehl aus, um das Image auszuführen:

docker run -p 8888:8888 goweb_app

Das Flag -p wird verwendet, um die Portbindung zu definieren. Da die Anwendung im Container auf Port 8888 läuft, binden wir sie ebenfalls an den Host-Port 8888. Wenn Sie eine Bindung an einen anderen Port herstellen möchten, können Sie -p $HOST_PORT:8888 verwenden. Beispielsweise -p 5000:8888.

Nun können wir testen, ob unser Webprogramm einwandfrei funktioniert. Öffnen Sie den Browser und geben Sie http://127.0.0.1:8888 ein. Der Antwortinhalt, den wir im Vorfeld definiert haben, wird wie folgt angezeigt:

Hallo liwenzhou.com!

Beispiel für stufenweisen Build

Nach dem Kompilieren unseres Go-Programms erhalten wir eine ausführbare Binärdatei. Tatsächlich wird der Go-Compiler im endgültigen Image nicht benötigt, das heißt, wir benötigen nur einen Container, um die endgültige Binärdatei auszuführen.

Eine der Best Practices für Docker besteht darin, die Image-Größe zu reduzieren, indem nur die Binärdateien behalten werden. Dazu verwenden wir eine Technik namens „Multi-Stage Builds“, was bedeutet, dass wir das Image in mehreren Schritten erstellen.

VON golang:alpine ALS Builder

# Setzen Sie die notwendigen Umgebungsvariablen ENV GO111MODULE=on für unser Image \
 CGO_ENABLED=0 \
 GOOS=linux \
 GOARCH=amd64

# Wechseln Sie in das Arbeitsverzeichnis: /build
ARBEITSVERZEICHNIS /build

# Den Code in den Container COPY kopieren. .

# Kompilieren Sie unseren Code in eine binäre ausführbare Datei app
Führen Sie „go build -o app“ aus.

###################
# Als nächstes erstellen Sie einen kleinen Spiegel#######################
VON Grund auf

# Kopieren Sie /dist/app vom Builder-Image in das aktuelle Verzeichnis COPY --from=builder /build/app /

# Auszuführender Befehl ENTRYPOINT ["/app"]

Mithilfe dieser Technik haben wir den Prozess der Kompilierung einer ausführbaren Binärdatei unter Verwendung von golang:alpine als Build-Image entfernt und ein einfaches, sehr kleines neues Image auf Basis von Scratch generiert. Wir kopieren die Binärdateien vom ersten Image mit dem Namen „Builder“ in das neu erstellte Scratch-Image. Weitere Informationen zum Scratch-Image finden Sie unter https://hub.docker.com/_/scratch

Bereitstellungsbeispiel mit zusätzlichen Dateien

Hier nehme ich das kleine Listenprojekt in meinem vorherigen „Go Web Video Tutorial“ als Beispiel. Die Github-Repository-Adresse des Projekts lautet: https://github.com/Q1mi/bubble.

Wenn das Projekt statische Dateien oder Konfigurationsdateien enthält, müssen diese in die endgültige Image-Datei kopiert werden.

Unser Bubble-Projekt verwendet statische Dateien und Konfigurationsdateien. Die spezifische Verzeichnisstruktur ist wie folgt:

Blase
├── README.md
├── Blase
├── Konf
│ └── config.ini
├── Controller
│ └── controller.go
├── dao
│ └── mysql.go
├── beispiel.png
├── go.mod
├── go.sum
├── main.go
├── Modelle
│ └── todo.go
├── Router
│ └── routers.go
├── Einstellung
│ └── Einstellung.go
├── statisch
│ ├── CSS
│ │ ├── app.8eeeaf31.css
│ │ └── chunk-vendors.57db8905.css
│ ├── Schriftarten
│ │ ├── element-icons.535877f5.woff
│ │ └── element-icons.732389de.ttf
│ └── js
│ ├── app.007f9690.js
│ └── chunk-vendors.ddcb6f91.js
└── Vorlagen
 ├── favicon.ico
 └── index.html

Wir müssen den Inhalt der Ordner „Templates“, „Static“ und „Conf“ in die endgültige Bilddatei kopieren. Das aktualisierte Dockerfile sieht wie folgt aus

VON golang:alpine ALS Builder

# Setzen Sie die notwendigen Umgebungsvariablen ENV GO111MODULE=on für unser Image \
 CGO_ENABLED=0 \
 GOOS=linux \
 GOARCH=amd64

# Wechseln Sie in das Arbeitsverzeichnis: /build
ARBEITSVERZEICHNIS /build

# Kopieren Sie die Dateien go.mod und go.sum in das Projekt und laden Sie die Abhängigkeitsinformationen herunter. KOPIEREN Sie go.mod.
KOPIEREN Sie go.sum.
RUN go mod herunterladen

# Den Code in den Container COPY kopieren. .

# Kompilieren Sie unseren Code in eine binäre ausführbare Dateiblase
RENNEN, los, bauen -o Blase.

###################
# Als nächstes erstellen Sie einen kleinen Spiegel#######################
VON Grund auf

KOPIEREN ./templates /templates
KOPIEREN ./static /static
KOPIEREN ./conf /conf

# Kopiere /dist/app vom Builder-Image in das aktuelle Verzeichnis COPY --from=builder /build/bubble /

# Befehl zum Ausführen von ENTRYPOINT ["/bubble", "conf/config.ini"]

Vereinfacht ausgedrückt sind noch ein paar weitere COPY-Schritte nötig. Schaut euch einfach die Kommentare im Dockerfile an.

Tipps: Platzieren Sie hier die Schritte zum KOPIEREN statischer Dateien in der oberen Ebene und zum KOPIEREN binärer ausführbarer Dateien in der unteren Ebene und versuchen Sie, mehr Cache zu verwenden.

Verknüpfen anderer Container

Da in unserem Projekt MySQL verwendet wird, können wir mit dem folgenden Befehl einen MySQL-Container starten. Sein Alias ​​ist mysql8019; das Passwort des Root-Benutzers ist root1234; mounten Sie /var/lib/mysql im Container im lokalen Verzeichnis /Users/q1mi/docker/mysql; der interne Service-Port ist 3306, der dem externen Port 13306 zugeordnet ist.

docker run --name mysql8019 -p 13306:3306 -e MYSQL_ROOT_PASSWORD=root1234 -v /Benutzer/q1mi/docker/mysql:/var/lib/mysql -d mysql:8.0.19

Hier müssen wir die in unserem Programm konfigurierte MySQL-Hostadresse in den Containeralias ändern, damit sie intern über den Alias ​​kommunizieren können (hier mysql8019).

[mysql]
Benutzer = root
Passwort = root1234
Host = mysql8019
Port = 3306
db = Blase

Denken Sie daran, das Bubble_App-Image nach der Änderung neu zu erstellen:

Docker-Build. -t Bubble_App

Wenn wir hier den Bubble_App-Container ausführen, müssen wir ihn mit der Methode --link mit dem obigen mysql8019-Container verknüpfen. Die spezifischen Befehle lauten wie folgt:

docker run --link=mysql8019:mysql8019 -p 8888:8888 bubble_app

Docker-Compose-Modus

Zusätzlich zur Verwendung der Methode --link zum Verknüpfen zweier Container wie oben können wir auch Docker Compose verwenden, um mehrere Container zu definieren und auszuführen.

Compose ist ein Tool zum Definieren und Ausführen von Docker-Anwendungen mit mehreren Containern. Mit Compose verwenden Sie YML-Dateien, um alle Dienste zu konfigurieren, die Ihre Anwendung benötigt. Anschließend können Sie mit einem einzigen Befehl alle Dienste aus der YML-Dateikonfiguration erstellen und starten.

Die Verwendung von Compose erfolgt grundsätzlich in drei Schritten:

  1. Verwenden Sie Dockerfile, um Ihre Anwendungsumgebung zu definieren, sodass sie überall repliziert werden kann.
  2. Definieren Sie die Dienste, aus denen Ihre Anwendung besteht, in docker-compose.yml, damit sie in isolierten Umgebungen zusammen ausgeführt werden können.
  3. Führen Sie den Befehl „Docker-Compose Up“ aus, um die gesamte Anwendung zu starten und auszuführen.

Unser Projekt erfordert zwei Container, um MySQL bzw. Bubble_App auszuführen. Der Inhalt der von uns geschriebenen Datei docker-compose.yml lautet wie folgt:

#yaml-Konfigurationsversion: „3.7“
Leistungen:
 mysql8019:
 Bild: "mysql:8.0.19"
 Häfen:
  - „33061:3306“
 Befehl: "--default-authentication-plugin=mysql_native_password --init-file /data/application/init.sql"
 Umfeld:
  MYSQL_ROOT_PASSWORD: "root1234"
  MYSQL_DATABASE: "Blase"
  MYSQL_PASSWORD: "root1234"
 Bände:
  - ./init.sql:/data/application/init.sql
 bubble_app:
 bauen: .
 Befehl: sh -c "./wait-for.sh mysql8019:3306 -- ./bubble ./conf/config.ini"
 hängt ab von:
  -mysql8019
 Häfen:
  - „8888:8888“

Diese Compose-Datei definiert zwei Dienste: bubble_app und mysql8019. In:

bubble_app
Verwenden Sie die Dockerfile-Datei im aktuellen Verzeichnis, um das Image zu erstellen, geben Sie die Abhängigkeit vom Dienst mysql8019 über depends_on an, deklarieren Sie den Dienstport 8888 und binden Sie den externen Port 8888.

mysql8019
Der Dienst mysql8019 verwendet das öffentliche Image mysql:8.0.19 von Docker Hub mit dem internen Port 3306 und dem externen Port 33061.

Hierbei ist zu beachten, dass unser Bubble_App-Container warten muss, bis der MySQL8019-Container normal gestartet ist, bevor er einen Startversuch unternimmt, da unser Webprogramm beim Start die MySQL-Verbindung initialisiert. Hier gibt es zwei Stellen, an denen Änderungen vorgenommen werden müssen. Die erste besteht darin, den letzten Satz in unserer Docker-Datei auszukommentieren:

# Docker-Datei
...
# Auszuführende Befehle (kommentieren Sie diesen Satz, da wir warten müssen, bis MySQL gestartet ist, bevor wir unser Webprogramm starten)
# EINSTIEGSPUNKT ["/bubble", "conf/config.ini"]

Zweitens fügen Sie den folgenden Befehl unter bubble_app hinzu und verwenden das vorgefertigte Skript wait-for.sh, um zu erkennen, ob mysql8019:3306 normal ist, bevor Sie den nachfolgenden Befehl zum Starten der Webanwendung ausführen:

Befehl: sh -c "./wait-for.sh mysql8019:3306 -- ./bubble ./conf/config.ini"

Da wir jetzt den sh-Befehl im Bubble_App-Image ausführen werden, können wir natürlich nicht das Scratch-Image verwenden, um es zu erstellen. Stattdessen verwenden wir debian:stretch-slim. Gleichzeitig müssen wir auch Netcat installieren, das vom Skript wait-for.sh verwendet wird. Vergessen Sie zum Schluss nicht, die Skriptdatei wait-for.sh in das endgültige Image zu kopieren und Ausführungsberechtigungen zu erteilen. Der aktualisierte Dockerfile-Inhalt lautet wie folgt:

VON golang:alpine ALS Builder

# Setzen Sie die notwendigen Umgebungsvariablen ENV GO111MODULE=on für unser Image \
 CGO_ENABLED=0 \
 GOOS=linux \
 GOARCH=amd64

# Wechseln Sie in das Arbeitsverzeichnis: /build
ARBEITSVERZEICHNIS /build

# Kopieren Sie die Dateien go.mod und go.sum in das Projekt und laden Sie die Abhängigkeitsinformationen herunter. KOPIEREN Sie go.mod.
KOPIEREN Sie go.sum.
RUN go mod herunterladen

# Den Code in den Container COPY kopieren. .

# Kompilieren Sie unseren Code in eine binäre ausführbare Dateiblase
RENNEN, los, bauen -o Blase.

###################
# Als nächstes erstellen Sie einen kleinen Spiegel#######################
VON debian:stretch-slim

KOPIEREN ./wait-for.sh /
KOPIEREN ./templates /templates
KOPIEREN ./static /static
KOPIEREN ./conf /conf


# Kopiere /dist/app vom Builder-Image in das aktuelle Verzeichnis COPY --from=builder /build/bubble /

RUN set -eux; \
 apt-get update; \
 apt-get install -y \
 --no-install-recommends \
 Netzkatze; \
  chmod 755 warte auf.sh

# Auszuführender Befehl # ENTRYPOINT ["/bubble", "conf/config.ini"]

Wenn alle Bedingungen erfüllt sind, können Sie den folgenden Befehl ausführen:

Docker-Compose-Up - Entwicklerhandbuch für Windows

Das vollständige Codebeispiel finden Sie in meinem GitHub-Repository: https://github.com/Q1mi/deploy_bubble_using_docker.

Zusammenfassen

Der Einsatz von Docker-Containern kann unsere Tätigkeiten bei der Konfiguration abhängiger Umgebungen deutlich vereinfachen, stellt jedoch auch höhere Anforderungen an unsere technischen Reserven. Unabhängig davon, ob Sie mit Docker vertraut sind oder nicht, dreht sich das Rad der technologischen Entwicklung weiter.

Referenzlinks:

https://levelup.gitconnected.com/complete-guide-to-create-docker-container-for-your-golang-application-80f3fb59a15e

Dies ist das Ende dieses Artikels zur Verwendung von Docker zum Bereitstellen von Go Web-Anwendungen. Weitere Informationen zur Docker-Bereitstellung von Go Web finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen!

Das könnte Sie auch interessieren:
  • Detaillierte Erläuterung zur Verwendung von Docker zum Bereitstellen der Django + MySQL8-Entwicklungsumgebung
  • Detailliertes Tutorial zum Bereitstellen eines Django-Projekts mit Docker auf CentOS8
  • Methoden und Schritte zum Bereitstellen von Go-Projekten basierend auf Docker-Images
  • Implementierung von zwei Basis-Images für die Docker-Bereitstellung von Go
  • Allgemeine Befehle zum Bereitstellen von InfluxDB und Mongo mit Docker
  • So verwenden Sie Docker-Compose, um Django-Anwendungen offline bereitzustellen
  • Beispiel für die Bereitstellung eines Django-Projekts mit Docker
  • Beispiel für die Bereitstellung einer Django-Anwendung mit Docker
  • Detaillierte Schritte zum Erstellen einer Golang-Online-Bereitstellungsumgebung mit Docker

<<:  Tutorial zur HTML-Tabellenauszeichnung (10): Zell-Padding-Attribut CELLPADDING

>>:  ElementUI implementiert Beispielcode für Dropdown-Optionen und Mehrfachauswahlfelder

Artikel empfehlen

MySQL verwendet frm-Dateien und ibd-Dateien, um Tabellendaten wiederherzustellen

Inhaltsverzeichnis Einführung in FRM-Dateien und ...

Einige „Fallstricke“ beim Upgrade der MySQL-Datenbank

Bei kommerziellen Datenbanken hat die Datenbankak...

Ein- und Ausblenden von HTML-Elementen durch Anzeige oder Sichtbarkeit

Manchmal müssen wir steuern, ob HTML-Elemente auf ...

HTML 5 Vorschau

<br />Original: http://www.alistapart.com/ar...

Häufig verwendete HTML-Meta-Enzyklopädie (empfohlen)

Der Meta-Tag ist ein Hilfstag im Head-Bereich der...

Einige Hinweise zum Ändern des innodb_data_file_path-Parameters von MySQL

Vorwort innodb_data_file_path wird verwendet, um ...

Zusammenfassung der CSS-Schwebeelementanalyse

Float: links/rechts/keine; 1. Gleichstufiges Schw...

So ändern Sie die Kodierung der MySQL-Datenbank in utf8mb4

Die utf8mb4-Kodierung ist eine Obermenge der utf8...

Erstellen Sie ein SSL-Zertifikat, das in nginx und IIS verwendet werden kann

Inhaltsverzeichnis Erstellen eines SSL-Zertifikat...

VMware Workstation 12 installiert Ubuntu 14.04 (64 Bit)

1. Installationsumgebung Computermodell: Lenovo Y...

Beispiel zum Einbetten von H5 in die Webansicht des WeChat-Applets

Vorwort WeChat-Miniprogramme bieten neue offene F...

Gründe und Lösungen für die Auswahl des falschen Index durch MySQL

In MySQL können Sie mehrere Indizes für eine Tabe...

Zusammenfassung der vier Klick-Antwortmethoden von Button

Button wird ziemlich oft verwendet. Hier habe ich...

Zusammenfassung der Browserkompatibilität gängiger CSS-Eigenschaften (empfohlen)

Warum müssen wir die Browserkompatibilität von CS...

Beispielcode zur Implementierung eines 3D-Rotationseffekts mit reinem CSS

Verwenden Sie hauptsächlich die Eigenschaften „pr...