In diesem Artikel wird erläutert, wie Sie Backend, Frontend und Gateway mithilfe von Docker-Containern ausführen und schließlich DockerCompose zur Container-Orchestrierung verwenden. Technologie-StackFrontend
hinteres Ende
Tor
Backend-Build-API Obwohl wir hier EXPOSE 4182 geschrieben haben, wird dies nur während des Tests verwendet. Tatsächlich werden wir den Backend-Schnittstellenport in der Produktionsumgebung nicht verfügbar machen. VON golang:1.15.5 LABEL-Betreuer="K8sCat <[email protected]>" EXPOSE 4182 ENV GOPROXY=https://goproxy.cn,direkt \ GO111MODULE=ein ARBEITSVERZEICHNIS /go/src/github.com/k8scat/containerized-app/api KOPIEREN . . RUN go mod herunterladen && \ gehe bauen -o api main.go && \ chmod +x api EINSTIEGSPUNKT [ "./api" ] Frontend-Web-Erstellung Erwähnenswert ist hier, dass das Front-End definitiv die Back-End-Schnittstelle aufruft und sich die Adresse dieser Schnittstelle je nach Bereitstellung ändert. Ein weiterer Punkt ist, dass einige Freunde definitiv feststellen werden, dass Entrypoint und CMD hier gleichzeitig verwendet werden. Dies dient dazu, den Front-End-Port während des Betriebs anzupassen, aber tatsächlich müssen wir ihn hier nicht anpassen, da Nginx hier letztendlich zum Weiterleiten verwendet wird. VON Knoten:lts LABEL-Betreuer="K8sCat <[email protected]>" ARBEITSVERZEICHNIS /web KOPIEREN . . ARG REACT_APP_BASE_URL Führen Sie npm config set registry https://registry.npm.taobao.org aus und führen Sie Folgendes aus: npm installieren && \ npm führt Build aus && \ npm install -g serve EINSTIEGSPUNKT [ "dienen", "-s", "bauen" ] CMD [ "-l", "3214" ] Torbau Torbau Nginx-Konfiguration Hier legen wir jeweils den Upstream des Backends und des Frontends fest und legen dann die Standortregeln für die Weiterleitung fest.
Upstream-Web { Server ca-web:3214; } Upstream-API { Server ca-API:4182; } Server { set_by_lua $corp_id 'return os.getenv("CORP_ID")'; set_by_lua $agent_id 'return os.getenv("AGENT_ID")'; set_by_lua $secret 'return os.getenv("GEHEIM")'; set_by_lua $callback_host 'return os.getenv("CALLBACK_HOST")'; set_by_lua $callback_schema 'return os.getenv("CALLBACK_SCHEMA")'; set_by_lua $callback_uri 'return os.getenv("CALLBACK_URI")'; set_by_lua $logout_uri 'return os.getenv("LOGOUT_URI")'; set_by_lua $token_expires 'Rückgabe os.getenv("TOKEN_EXPIRES")'; set_by_lua $use_secure_cookie 'return os.getenv("USE_SECURE_COOKIE")'; hören Sie 443 SSL http2; Servername $Hostname; Resolver 8.8.8.8; SSL-Zertifikat /certs/cert.crt; SSL-Zertifikatschlüssel /certs/cert.key; ssl_session_cache geteilt:SSL:1m; SSL-Sitzungszeitüberschreitung 5 Min. SSL-Protokolle TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers AESGCM:HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers ein; : lua_ssl_verify_depth 2; lua_ssl_trusted_certificate /etc/pki/tls/certs/ca-bundle.crt; wenn ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2})") { Setze $year auf $1; Setze $Monat $2; Setze $Tag $3; } access_log Protokolle/access_$Jahr$Monat$Tag.log Haupt; Fehlerprotokollprotokolle/Fehler.log; Zugriff über Lua-Datei "/usr/local/openresty/nginx/conf/gateway.lua"; Standort ^~ /gateway { Stamm-HTML; Index Index.html Index.htm; } Standort ^~ /api { Proxy-Passwort http://API; Proxy_Lese_Timeout 3600; Proxy_http_Version 1.1; Proxy_Set_Header X_FORWARDED_PROTO https; Proxy_Set_Header X-Real-IP $Remote_Addr; proxy_set_header X-Weitergeleitet-Für $remote_addr; proxy_set_header X-Weitergeleitet-Für $proxy_add_x_forwarded_for; Proxy_Set_Header Host $host; proxy_set_header Verbindung ""; } Standort ^~ / { Proxy-Passwort http://Web; Proxy_Lese_Timeout 3600; Proxy_http_Version 1.1; Proxy_Set_Header X_FORWARDED_PROTO https; Proxy_Set_Header X-Real-IP $Remote_Addr; proxy_set_header X-Weitergeleitet-Für $remote_addr; proxy_set_header X-Weitergeleitet-Für $proxy_add_x_forwarded_for; Proxy_Set_Header Host $host; proxy_set_header Verbindung ""; } Fehlerseite 500 502 503 504 /50x.html; Standort = /50x.html { Stamm-HTML; } } Server { hören Sie 80; Servername $Hostname; Standort / { Umleitung von ^/(.*) https://$server_name/$1 neu schreiben; } } Docker-DateiVON openresty/openresty:1.19.3.1-centos LABEL-Betreuer="K8sCat <[email protected]>" KOPIEREN gateway.conf /etc/nginx/conf.d/gateway.conf KOPIEREN Sie gateway.lua /usr/local/openresty/nginx/conf/gateway.lua KOPIEREN Sie nginx.conf /usr/local/openresty/nginx/conf/nginx.conf # Installieren Sie lua-resty-http RUN /usr/local/openresty/luajit/bin/luarocks installiere lua-resty-http Lua implementiert Gateway-Authentifizierung basierend auf Enterprise WeChat Einige der hier aufgeführten Konfigurationsparameter werden durch den Abruf von von Nginx festgelegten Variablen ermittelt. lokales JSON = erforderlich("cjson") lokales http = erforderlich("resty.http") lokale URI = ngx.var.uri lokale uri_args = ngx.req.get_uri_args() lokales Schema = ngx.var.scheme lokale Firmen-ID = ngx.var.corp_id lokale Agenten-ID = ngx.var.agent_id lokales Geheimnis = ngx.var.secret lokales Callback-Schema = ngx.var.callback_scheme oder Schema lokaler Rückrufhost = ngx.var.callback_host lokale Rückruf-URI = ngx.var.callback_uri lokales use_secure_cookie = ngx.var.use_secure_cookie == "true" oder false lokale Rückruf-URL = Rückrufschema .. "://" .. Rückrufhost .. Rückruf-URI lokale Umleitungs-URL = Rückrufschema .. "://" .. Rückrufhost .. ngx.var.request_uri lokale Logout-URI = ngx.var.logout_uri oder „/logout“ lokales token_expires = ngx.var.token_expires oder „7200“ token_expires = bisNummer(token_expires) lokale Funktion request_access_token(code) lokale Anfrage = http.new() Anfrage:set_timeout(7000) lokale Auflösung, Fehler = Anfrage: Anfrage-URI("https://qyapi.weixin.qq.com/cgi-bin/gettoken", { Methode = "GET", Abfrage = { corpid = Firmen-ID, corpsecret = geheim, }, ssl_verify = wahr, }) wenn nicht res dann returniere nil, (Fehler oder „Anforderung des Zugriffstokens fehlgeschlagen: “ .. (Fehler oder „unbekannter Grund“)) Ende wenn res.status ~= 200 dann return nil, „erhalten „ .. res.status .. “ von https://qyapi.weixin.qq.com/cgi-bin/gettoken: „ .. res.body Ende lokale Daten = json.decode(res.body) wenn data["errcode"] ~= 0 dann returniere nil, data["errmsg"] anders Daten zurückgeben["Zugriffstoken"] Ende Ende lokale Funktion request_user(access_token, code) lokale Anfrage = http.new() Anfrage:set_timeout(7000) lokale Auflösung, Fehler = Anfrage: Anfrage-URI("https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo", { Methode = "GET", Abfrage = { Zugriffstoken = Zugriffstoken, Code = Code, }, ssl_verify = wahr, }) wenn nicht res dann return nil, „Anforderung zum Abrufen des Profils fehlgeschlagen:“ .. (Fehler oder „unbekannter Grund“) Ende wenn res.status ~= 200 dann return nil, „erhalten „ .. res.status .. „ von https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo“ Ende lokale Benutzerinformationen = json.decode(res.body) wenn userinfo["errcode"] == 0 dann wenn userinfo["Benutzer-ID"] dann res, err = Anfrage: Anfrage-URI("https://qyapi.weixin.qq.com/cgi-bin/user/get", { Methode = "GET", Abfrage = { Zugriffstoken = Zugriffstoken, Benutzer-ID = Benutzerinfo["Benutzer-ID"], }, ssl_verify = wahr, }) wenn nicht res dann return nil, „Abrufen der Benutzeranforderung fehlgeschlagen:“ .. (Fehler oder „unbekannter Grund“) Ende wenn res.status ~= 200 dann return nil, „erhalten „ .. res.status .. „ von https://qyapi.weixin.qq.com/cgi-bin/user/get“ Ende lokaler Benutzer = json.decode(res.body) wenn Benutzer["Fehlercode"] == 0 dann Benutzer zurückgeben anders returniere nil, Benutzer["errmsg"] Ende anders return nil, „Benutzer-ID existiert nicht“ Ende anders returniere nil, Benutzerinfo["errmsg"] Ende Ende lokale Funktion is_authorized() lokale Header = ngx.req.get_headers() lokales Ablaufdatum = tonumber(ngx.var.cookie_OauthExpires) oder 0 lokale Benutzer-ID = ngx.unescape_uri(ngx.var.cookie_OauthUserID oder "") lokales Token = ngx.var.cookie_OauthAccessToken oder "" wenn expires == 0 und headers["OauthExpires"] dann läuft ab = tonumber(headers["OauthExpires"]) Ende wenn user_id:len() == 0 und headers["OauthUserID"] dann Benutzer-ID = Header["OauthUserID"] Ende wenn token:len() == 0 und headers["OauthAccessToken"] dann Token = Header["OauthAccessToken"] Ende lokales expect_token = callback_host .. user_id .. läuft ab wenn token == expect_token und abläuft dann wenn abläuft > ngx.time() dann returniere wahr anders return false Ende anders return false Ende Ende lokale Funktion redirect_to_auth() return ngx.redirect("https://open.work.weixin.qq.com/wwopen/sso/qrConnect?" .. ngx.encode_args({ appid = Firmen-ID, agentid = agenten-id, Umleitungs-URI = Rückruf-URL, Status = Umleitungs-URL })) Ende lokale Funktion autorisieren() wenn uri ~= callback_uri dann returniere redirect_to_auth() Ende lokaler Code = uri_args["Code"] wenn nicht Code, dann ngx.log(ngx.ERR, „Code von https://open.work.weixin.qq.com/wwopen/sso/qrConnect nicht erhalten“) gibt ngx.exit(ngx.HTTP_FORBIDDEN) zurück. Ende lokales Zugriffstoken, Anforderungszugriffstoken_Fehler = Anforderungszugriffstoken(Code) wenn nicht access_token dann ngx.log(ngx.ERR, „Fehler bei der Anforderung des Zugriffstokens: " .. request_access_token_err) gibt ngx.exit(ngx.HTTP_FORBIDDEN) zurück. Ende lokaler Benutzer, request_user_err = request_user(Zugriffstoken, Code) wenn nicht Benutzer, dann ngx.log(ngx.ERR, "Fehler bei der Profilanforderung: " .. request_user_err) gibt ngx.exit(ngx.HTTP_FORBIDDEN) zurück. Ende ngx.log(ngx.ERR, "Benutzer-ID: " .. Benutzer["Benutzer-ID"]) lokal läuft ab = ngx.time() + token_expires local cookie_tail = "; version=1; path=/; Max-Age=" .. läuft ab wenn use_secure_cookie dann cookie_tail = cookie_tail .. "; sicher" Ende lokale Benutzer-ID = Benutzer["Benutzer-ID"] lokales Benutzertoken = Rückrufhost .. Benutzer-ID .. läuft ab ngx.header["Cookie setzen"] = { "OauthUserID=" .. ngx.escape_uri(Benutzer-ID) .. cookie_tail, "OauthAccessToken=" .. ngx.escape_uri(Benutzertoken) .. cookie_tail, "OauthExpires=" .. läuft ab .. cookie_tail, } returniere ngx.redirect(uri_args["Status"]) Ende lokale Funktion handle_logout() wenn uri == logout_uri dann ngx.header["Set-Cookie"] = "OauthAccessToken==gelöscht; Pfad=/; läuft ab=Do, 01. Jan. 1970 00:00:00 GMT" --return ngx.redirect("/") Ende Ende handle_logout() wenn (nicht is_authorized()), dann autorisieren() Ende Container-Orchestrierung mit DockerComposeHier sind einige Punkte zu erwähnen:
Version: "3.8" Leistungen: API: Erstellen: ./api Bild: ca-api:latest Containername: ca-api Webseite: bauen: Kontext: ./Web Argumente: REACT_APP_BASE_URL: https://example.com/api Bild: ca-web:latest Containername: ca-web Tor: Erstellen: ./gateway Bild: ca-gateway:latest Hostname: example.com Bände: - ./gateway/certs/fullchain.pem:/certs/cert.crt - ./gateway/certs/privkey.pem:/certs/cert.key Häfen: - 80:80 -443:443 Umfeld: -CORP_ID= -AGENT_ID= -GEHEIM= - CALLBACK_HOST=example.com – CALLBACK_SCHEMA=https – CALLBACK_URI=/gateway/oauth_wechat -LOGOUT_URI=/gateway/oauth_logout -TOKEN_EXPIRES=7200 - USE_SECURE_COOKIE=true Containername: ca-gateway Offener Quellcode GitHub https://github.com/k8scat/containerized-app Dies ist das Ende dieses Artikels über die Docker+DockerCompose-Verpackung von Webanwendungen. Weitere relevante Inhalte zur Docker+DockerCompose-Verpackung von Webanwendungen finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird! Das könnte Sie auch interessieren:
|
<<: Teilen Sie 20 hervorragende Beispiele für Webformular-Design
1. Legen Sie eine Verzeichnis-Whitelist fest: Leg...
Wenn Sie mit dem Erlernen von Linux beginnen, müs...
Daten-URI Data URI ist ein durch RFC 2397 definie...
Code kopieren Der Code lautet wie folgt: <ifra...
Vorlage <el-table :data="Datenliste"...
Inhaltsverzeichnis 1. Problematische SQL-Anweisun...
Durch die Verwendung des prozentualen Padding-Top...
Auswählen oder Erstellen einer Abonnementnachrich...
Vorwort Um zum Originalcode kompatibel zu sein, b...
SpringBoot ist wie eine riesige Python, die sich ...
Docker erfreut sich immer größerer Beliebtheit. E...
Klicken Sie hier, um zum Abschnitt „HTML-Tutorial“...
Überblick: Das Dateisystemmodul ist ein einfacher...
1. Laden Sie die JDK-Download-Adresse herunter我下載...
Verwenden Sie das Linux-Dienstprogramm certbot, u...