誰從未懷疑過自己是否為應用程式建立了正確的 Docker 映像?嗯,這個問題我已經問過好幾次了,但我幾乎總是不知道自己這樣做是對還是錯。
因此,在本文中,我們將探索為Go 應用程式創建高效且優化的Docker 映像的高級實踐,我們將比較不同的方法,例如使用alpine 和scrap 基礎鏡像,並透過程式碼討論每種方法的優點。範例和性能分析。
首先,讓我們為容器化 Go 應用程式建立一個典型的專案結構。
舉個例子,我正在使用這個應用程序,它是一個 URL 縮短器:
url_shortener ├── cmd │ └── main.go ├── internal │ ├── monitoring │ │ └── prometheus.go │ ├── server │ │ └── server.go │ └── shortener │ ├── model.go │ ├── repository.go │ ├── service.go │ └── service_test.go ├── pkg │ ├── api │ │ └── shortener │ │ ├── handler.go │ │ └── handler_integration_test.go │ └── utils │ └── base62 │ ├── hash.go │ └── hash_test.go ├── Dockerfile ├── Dockerfile.alpine ├── Dockerfile.golang ├── README.md ├── compose.yml ├── go.mod ├── go.sum └── prometheus.yml
很少人知道我們不需要在生產環境中執行「完整」的鏡像。例如,Ubuntu 具有我們語言的所有軟體包、原始碼、擴充和 SDK。我們可以簡單地使用 SDK 在系統中建立我們的應用程序,然後將建置複製到僅運行該建置的較小的最佳化映像。這就是多階段發揮作用的地方。
在 Dockerfile 中,您可以定義多個建置階段,每個階段都會以 FROM 語句開始。第一階段可用於編譯程式碼、安裝依賴項、執行測試等。在後續階段,您可以僅將必要的工件(例如編譯的二進位檔案)複製到最終映像,丟棄執行應用程式不需要的所有內容。
# syntax=docker/dockerfile:1 # Build stage FROM golang:1.22-alpine AS builder WORKDIR /app COPY . . RUN go mod download RUN go build -o url-shortener ./cmd # Final stage FROM alpine:latest WORKDIR /app COPY --from=builder /app/url-shortener . CMD ["./url-shortener"]
該死的Rafa,但是你用「這兩張圖」做什麼?首先,我使用映像作為建構器,這是我們創建應用程式執行檔的地方:
第一階段(建造階段):
然後,我使用一個較小的映像來運行我們在第一步中產生的可執行檔:
第二階段(最後階段):
如果我們想確認到底發生了什麼,在 Docker Desktop 中可以分析映像的層次結構。在裡面我們可以看到他使用的東西:
現在我們也可以分析剛剛產生的圖片的大小,在本例中是 url-shortener:alpine,約 30mb:
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE url-shortener alpine aa99d6a2c028 3 minutes ago 29.9MB
Alpine 是一個極簡、安全、輕量級的 Linux 發行版,因其高效和簡單而廣泛應用於容器環境。它為建立可擴展的應用程式提供了堅實的基礎,而無需其他較重的 Linux 發行版的開銷。
在我們的應用程式中使用 Alpine 的一些優勢主要與以下 3 個支柱相關:
好的,但是如果我使用相同的 SDK 版本(在本例中為 golang:1.22-alpine)怎麼辦?我的應用程式有多大?
REPOSITORY TAG IMAGE ID CREATED SIZE url-shortener golang-alpine d615d75c3aff 25 minutes ago 251MB
好吧,在這種情況下,我們最終得到了大約 250mb 的圖像...而與阿爾卑斯山相比,我們純粹去了大約 30mb,這已經是一個很大的差異了。還能進一步改進嗎?
答案是肯定的,讓我們來詳細了解
Scratch 是 Docker 中一個特殊且非常簡約的映像。它實際上是您可以使用的最簡單、最空的基礎映像。它絕對不包含任何內容:沒有作業系統、沒有函式庫、沒有工具——它實際上是一個空容器。
Essa abordagem minimalista traz benefícios significativos, especialmente em termos de segurança. Ao usar Scratch, você minimiza drasticamente a superfície de ataque, já que não há pacotes ou ferramentas adicionais que possam introduzir vulnerabilidades. Seu contêiner contém apenas o essencial para a execução do aplicativo, garantindo um ambiente imutável e previsível em qualquer situação.
# syntax=docker/dockerfile:1 # Build stage FROM golang:1.22-alpine AS builder WORKDIR /app COPY . . RUN go mod download RUN go build -o url-shortener ./cmd # Final stage with Scratch FROM scratch WORKDIR /app COPY --from=builder /app/url-shortener . CMD ["./url-shortener"]
E o resultado após criar as 3 imagens, nosso ranking de menor imagem ficou assim:
O Scratch conseguiu baixar mais alguns megas no tamanho final de nossa aplicação. Isso impacta no tamanho de arquivos transferidos pela rede, hoje algumas empresas cobram pela banda que trafegamos dentro dos servidores, e também pode influenciar em nosso Horizontal Scaling da aplicação.
Deixei os 3 Dockerfiles dentro do repositório do github caso você queira testar em seu próprio pc ?
A resposta mais tranquila para essa é "quase sempre", uma dica de cara é: ele vai muito bem com linguagens como Go, Rust, ou C/C++. Mas qui estão alguns pontos para levar em consideração na hora de escolher se deve ou não usar o scratch:
Usar o cache do Docker para otimizar o tempo de build é uma técnica essencial para evitar recompilar ou baixar dependências desnecessariamente em cada build. O Docker armazena em cache as camadas de cada etapa do Dockerfile, reutilizando-as sempre que possível.
Em projetos Go, baixar dependências com go mod download pode ser um processo demorado, especialmente se houver muitas dependências. Se você recompilar todas as dependências em cada build, isso aumenta significativamente o tempo de build.
Ao copiar apenas os arquivos go.mod e go.sum em uma etapa separada antes de copiar o código-fonte completo, você permite que o Docker use o cache dessa etapa se os arquivos go.mod e go.sum não tiverem mudado. Veja como fica nosso Docker file com as mudanças:
# syntax=docker/dockerfile:1 # Build stage FROM golang:1.22-alpine AS builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN go build -o url-shortener ./cmd # Final stage FROM scratch WORKDIR /app COPY --from=builder /app/url-shortener . CMD ["./url-shortener"]
Só de fazer esta pequena mudança já ganhamos dois pontos bem interessantes quando se trata de desenvolvimento de software, que são:
Menor tempo de build: Se não houver alterações nos arquivos go.mod e go.sum, o Docker reutiliza o cache, evitando o download das dependências e economizando tempo.
Eficiência no CI/CD: Em pipelines de integração contínua, essa técnica reduz o tempo de execução dos pipelines, aumentando a eficiência do desenvolvimento e entrega.
Então bora usar isso a nosso favor no dia-a-dia :)
Docker Scout é uma ferramenta da Docker integrada ao Docker Desktop que analisa suas imagens para identificar vulnerabilidades de segurança. Ele fornece insights sobre as dependências presentes em suas imagens e alerta sobre possíveis problemas, permitindo que você tome medidas corretivas antes de implantar suas aplicações.
Por que é importante? Manter suas imagens Docker seguras é fundamental para proteger suas aplicações contra ataques e exploração de vulnerabilidades. O Docker Scout automatiza o processo de análise, tornando mais fácil manter suas imagens seguras e atualizadas.
O Scout funciona praticamente com 2 passos, ele examina a imagem Docker, mapeia todas as dependências incluídas na imagem e verifica essas dependências em uma base de dados de vulnerabilidades conhecidas. Por fim, classifica as vulnerabilidades encontradas por severidade e fornece recomendações para corrigir ou mitigar os problemas.
透過這種方式,我們將進行主動預防,在將映像部署到生產環境之前識別並修正漏洞,以幫助防止可能的安全漏洞,並且我們還可以獲得營運效率,這是什麼意思?我們可以自動化漏洞分析,讓 DevOps 或安全團隊專注於糾正措施,而不是手動調查。
透過我們探索的實踐,您現在可以使用多階段建置等技術為Go 應用程式建立Docker 映像,這些技術可以減少映像大小,選擇alpine 或scrap 等基礎映像來提高安全性和效率,透過使用Docker Scout 來監控漏洞,您可以確保您的應用程式有效率且安全地運行。
這些做法不僅提高了技術性能,還為您的日常生活和公司帶來直接的效益,節省時間和資源。
因此,下次建立 Docker 映像時,請記住這些策略。應用它們並觀察結果。 ?
以上是Go + Docker:如何為 Golang 應用程式建立最佳的 Docker 映像的詳細內容。更多資訊請關注PHP中文網其他相關文章!