-
Monivaiheinen kääntäminen
Keskitaso
Dockerin hyvä tuntemus vaaditaan: Docker
Monivaiheiset koonnit
Monivaiheisten koontien ideana on helpottaa pienempien konttikuvien rakentamista siten, että väliaikaiset koontitiedostot voidaan jättää pois lopullisesta tuotteesta.
Pienemmät konttikuvat vievät vähemmän levytilaa, mikä tarkoittaa, että niiden lataaminen ja käyttöönotto vievät vähemmän aikaa. Ohjelmiston kääntämisen aikana tarvitaan usein kääntäjä, useita kirjastoriippuvuuksia ja väliaikaisia objekteja, joita ei tarvita ohjelman suorittamisen aikana. Monivaiheisten koontien avulla voit määritellä samassa Dockerfile-tiedostossa kaksi tai useampia Dockerin koontivaiheita. Ne suoritetaan järjestyksessä yksi toisensa jälkeen, ja kukin "vaihe" voi kopioida tiedostoja edellisistä vaiheista. Näin voimme helposti ja saman koontiprosessin aikana rakentaa ohjelmiston ja säilyttää lopuksi vain ne tiedostot, joita todella tarvitsemme suorittamiseen.
Käyttö
Luo ensin uusi Go-projekti tai käytä olemassa olevaa alustettua Go-projektia.
- Esimerkki uuden Go-projektin alustamisesta:
Otetaan tämä Dockerfile:
Dockerfile:
FROM golang:1.18.3-stretch as builder
RUN mkdir -p /go/src/server
WORKDIR /go/src/server
COPY go.mod go.sum ./
RUN go mod download && go mod verify
COPY . .
RUN CGO_ENABLED=0 go build server.go
FROM alpine:edge
RUN mkdir /app
COPY --from=builder /go/src/server/server /app/server
CMD ["/app/server"]
ja tämä koodi (Go):
server.go:
package main
import (
"fmt"
"strings"
"net/http"
"github.com/pborman/uuid"
)
func main() {
http.HandleFunc("/", func (w http.ResponseWriter, r *http.Request) {
uuidWithHyphen := uuid.NewRandom()
uuid := strings.Replace(uuidWithHyphen.String(), "-", "", -1)
fmt.Fprintf(w, "Welcome to my website!\n")
fmt.Fprintf(w, uuid)
})
fmt.Print("Starting server in port 8080...\n")
http.ListenAndServe(":8080", nil)
}
Suorita sitten go mod tidy, joka lataa kaikki lähdetiedostoissasi vaaditut riippuvuudet ja päivittää go.mod-tiedoston kyseisellä riippuvuudella. Tässä tapauksessa se lataa paketin github.com/pborman/uuid.
Dockerfile voidaan jakaa kahteen osaan (tai vaiheeseen), joista kumpikin alkaa FROM-ohjeella:
FROM golang:1.18.3-stretch as builderkäyttää virallista Golang-kuvaa, joka sisältää kaiken koodin kääntämiseen tarvittavan. Se nimetään tunnisteellabuilder. Kopioimmego.mod- jago.sum-tiedostot ja lataamme pakettiriippuvuudet "työhakemistoon". Kopioimme koko "työhakemiston", mukaan lukien koodin, komennollaCOPY . ., ja lopuksi käännämme koodin komennollaRUN CGO_ENABLED=0 go build server.go.FROM alpine:edgekäyttää minimaalistaalpine-jakelua. RivilläCOPY --from=builder /go/src/server/server /app/serverkopioidaan edellisestä vaiheesta (build) käännetty ohjelma ja vain käännetty ohjelma.
Tämän koontiprosessin testaamiseksi laita nämä kaksi tiedostoa samaan hakemistoon ja nimeä ne Dockerfile ja server.go. Suorita sitten komento:
Tämä tuottaa kuvan nimeltä go-server:latest. Tarkista kuvan koko suorittamalla:
$ docker images go-server
REPOSITORY TAG IMAGE ID CREATED SIZE
go-server latest 173c922261a3 16 minutes ago 12.1MB
koon pitäisi olla noin 12 Mt, josta yli puolet (~7 Mt) on käännettyä koodia.
Jos vedät kuvan golang:1.18.3-stretch (sen, jota käytimme koodin rakentamiseen) ja tarkistat sen koon, huomaat sen olevan noin 890 MB.
$ docker images golang:1.18.3-stretch
REPOSITORY TAG IMAGE ID CREATED SIZE
golang 1.18.3-stretch 6ee1deda35bd 12 days ago 890 MB
Sama pieni kuva (go-server:latest) on toki mahdollista saada aikaan myös muilla menetelmillä. Voit rakentaa koodin Dockerin ulkopuolella ja kopioida sen sitten alpine-kuvaan. Voit liittää koodihakemiston koontikuvaan, rakentaa sen ja kopioida sitten jälleen käännetyn tuotoksen alpine-kuvaan. Mikään näistä menetelmistä ei kuitenkaan ole yhtä helppo ja kompakti kuin tämä.
Käyttö Rahdissa
Tämän testaamiseksi Rahdissa tarvitsee vain kirjautua Rahtiin, valita oikea projekti ja suorittaa:
HUOM.: Koodin on oltava git-repositoriossa, ja Rahdin on pystyttävä kloonaamaan se.
Lopputuloksena syntyy kuva nimeltä multi-stage-build, joka tallennetaan valitsemasi projektin Rahdin sisäiseen rekisteriin. Tätä kuvaa voidaan sitten käyttää Rahdin käyttöönotossa image stream -vaihtoehdon avulla kuvaa käyttöönotettaessa.