Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Go + Docker: Cara mencipta imej Docker terbaik untuk aplikasi Golang

Go + Docker: Cara mencipta imej Docker terbaik untuk aplikasi Golang

WBOY
WBOYasal
2024-08-14 22:49:02346semak imbas

Siapa yang tidak pernah ragu-ragu sama ada mereka mencipta imej Docker yang betul untuk aplikasi mereka? Nah, saya telah mengalami keraguan ini beberapa kali dan saya hampir selalu tidak tahu sama ada saya melakukannya dengan betul atau salah.

Jadi dalam artikel ini, kami akan meneroka amalan lanjutan untuk mencipta imej Docker yang cekap dan dioptimumkan untuk aplikasi Go anda. Kami akan membandingkan pendekatan yang berbeza, seperti menggunakan imej asas alpine dan scratch, dan membincangkan faedah setiap satu, dengan kod contoh dan analisis prestasi.

Struktur projek

Pertama, mari kita wujudkan struktur projek tipikal untuk aplikasi Go dalam kontena.

Sebagai contoh, saya menggunakan aplikasi ini yang merupakan pemendek 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

1. Menulis Fail Docker

Apa yang segelintir orang tahu ialah kita tidak memerlukan imej "lengkap" yang dijalankan dalam pengeluaran. Contohnya, Ubuntu dengan semua pakej, sumber, sambungan dan SDK untuk bahasa kita. Kami hanya boleh membina apl kami dalam sistem dengan SDK dan kemudian menyalin binaan ke imej yang lebih kecil dan dioptimumkan yang hanya akan menjalankan binaan itu. Dan di situlah Berbilang Peringkat masuk.

Binaan Berbilang Peringkat

Dalam Fail Docker, anda boleh menentukan berbilang peringkat binaan, setiap satu bermula dengan pernyataan FROM. Peringkat pertama boleh digunakan untuk menyusun kod, memasang kebergantungan, menjalankan ujian, dsb. Dalam peringkat seterusnya, anda boleh menyalin hanya artifak yang diperlukan (seperti binari yang disusun) ke imej akhir, membuang semua yang tidak diperlukan untuk menjalankan aplikasi.

# 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"]

Sialan Rafa, tetapi apa yang anda lakukan dengan "dua imej ini"? Mula-mula saya menggunakan imej sebagai pembina, di mana kami mencipta aplikasi boleh laku:

Peringkat Pertama (Peringkat binaan):

  • Menggunakan golang:1.22-alpine sebagai imej asas.
  • Menyalin kod sumber ke bekas.
  • Muat turun kebergantungan dan susun perduaan aplikasi Go.

Pada masa itu, saya menggunakan imej yang lebih kecil yang hanya akan menjalankan boleh laku ini yang kami hasilkan dalam langkah pertama:

Peringkat Kedua (Peringkat Akhir):

  • Menggunakan alpine:latest sebagai imej asas, yang jauh lebih kecil dan hanya perlu mempunyai alatan yang diperlukan untuk menjalankan binari.
  • Menyalin binari yang disusun daripada peringkat sebelumnya (pembina) kepada imej baharu.
  • Mentakrifkan arahan pelaksanaan aplikasi.

Jika kami ingin mengesahkan apa yang sebenarnya berlaku, dalam Docker Desktop terdapat kemungkinan untuk menganalisis hierarki imej. Di dalam kita boleh lihat apa yang dia gunakan:

Go + Docker: Como criar as melhores imagens Docker para aplicações Golang

Kini kami juga boleh menganalisis saiz imej yang baru kami hasilkan ini, dalam kes ini url-shortener:alpine iaitu ~30mb:

$ docker images
REPOSITORY            TAG         IMAGE ID       CREATED              SIZE
url-shortener                 alpine          aa99d6a2c028   3 minutes ago    29.9MB

Tetapi apa itu Alpine?

Alpine ialah pengedaran Linux yang minimalis, selamat dan ringan, digunakan secara meluas dalam persekitaran kontena kerana kecekapan dan kesederhanaannya. Ia menyediakan asas yang kukuh untuk membina aplikasi berskala tanpa overhed pengedaran Linux lain yang lebih berat.

Beberapa kelebihan menggunakan Alpine dalam apl kami terutamanya dikaitkan dengan 3 tiang ini:

  • Fleksibiliti: Imej alpine (~5MB) adalah kecil dan termasuk pengurus pakej apk, membolehkan anda memasang kebergantungan tambahan yang diperlukan.
  • Keserasian: Sokongan untuk perpustakaan dinamik, menjadikannya sesuai untuk aplikasi yang bergantung pada perpustakaan luaran.
  • Keselamatan: Dikemas kini secara kerap, alpine menyertakan tampung keselamatan, mengurangkan risiko kelemahan.

Baiklah, tetapi bagaimana jika saya menggunakan versi SDK yang sama, dalam kes ini golang:1.22-alpine. Seberapa besar aplikasi saya?

REPOSITORY                    TAG             IMAGE ID       CREATED         SIZE
url-shortener                 golang-alpine   d615d75c3aff   25 minutes ago   251MB

Nah, dalam kes ini, kami mendapat imej dengan ~250mb... Walaupun dibandingkan dengan alpine, kami hanya mencapai ~30mb, ia sudah menjadi perbezaan yang besar. Dan bolehkah ia dipertingkatkan lagi?

Jawapannya YA, dan mari kita masuk ke butirannya

2. Pengoptimuman Lanjutan

2.1 Gores

Scratch ialah imej istimewa dan sangat minimalis dalam Docker. Ia sebenarnya imej asas yang paling mudah dan paling kosong yang boleh anda gunakan. Ia sama sekali tidak mengandungi apa-apa: tiada sistem pengendalian, tiada perpustakaan, tiada alatan — ia benar-benar bekas kosong.

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:

  1. url-shortener:scratch - 21.1MB
  2. url-shortener:alpine - 29.9MB
  3. url-shortener:golang-alpine - 251MB

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 ?

Quando devo usar o scratch

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:

  • Aplicações Statically Linked: Se sua aplicação não depende de bibliotecas dinâmicas e pode ser compilada de forma estática, Scratch é uma excelente escolha.
  • Segurança: Quando a segurança é uma prioridade e você quer minimizar a quantidade de software no contêiner.
  • Eficiência: Para criar imagens Docker extremamente pequenas e eficientes.

2.2 Reduzindo o Tempo de Build (Cache)

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.

Como arrumar isso?

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 :)

2.3 Melhorando a Segurança (Docker Scout)

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.

Como funciona?

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.

Contoh Praktikal: Menggunakan Pengakap Docker pada Desktop Docker

  1. Akses Desktop Docker: Buka Desktop Docker dan pergi ke tab "Imej". Di sini anda akan melihat senarai semua imej yang anda miliki secara tempatan. Dalam contoh ini saya menggunakan imej postgres:16-alpine, kerana ia mengandungi kelemahan yang boleh kita gunakan sebagai contoh. Go + Docker: Como criar as melhores imagens Docker para aplicações Golang
  2. Lakukan Analisis Keterdedahan: Pilih imej yang ingin anda analisis. Pengakap Docker secara automatik akan memaparkan kelemahan yang diketahui dalam imej yang dipilih. Anda akan melihat ikon status keselamatan di sebelah setiap imej, menunjukkan sama ada terdapat kelemahan yang perlu ditangani. Go + Docker: Como criar as melhores imagens Docker para aplicações Golang
  3. Lihat Butiran Kerentanan: Klik imej untuk melihat papan pemuka terperinci tentang kelemahan yang ditemui. Ini termasuk versi pakej yang terjejas, perihalan CVE dan keterukan. Anda juga boleh melihat sejarah imbasan dan perubahan, membantu anda menjejaki cara keselamatan imej telah berkembang dari semasa ke semasa. Go + Docker: Como criar as melhores imagens Docker para aplicações Golang
  4. Gunakan Pembetulan: Berdasarkan cadangan Pengakap Docker, anda boleh memutuskan untuk mengemas kini pakej, membina semula imej dengan asas yang lebih selamat atau mengambil tindakan pengurangan yang lain. Pembetulan boleh digunakan terus pada saluran paip Dockerfile atau CI/CD anda. Go + Docker: Como criar as melhores imagens Docker para aplicações Golang

Dan dengan cara ini, kami akan mempunyai pencegahan proaktif yang akan mengenal pasti dan membetulkan kelemahan sebelum imej digunakan dalam pengeluaran, membantu melindungi daripada kemungkinan eksploitasi keselamatan dan kami juga memperoleh kecekapan operasi, apakah yang saya maksudkan dengan itu? Kami boleh mengautomasikan analisis kerentanan, membenarkan DevOps atau pasukan keselamatan menumpukan pada tindakan pembetulan dan bukannya penyiasatan manual.

Kesimpulan

Dengan amalan yang telah kami terokai, anda kini mempunyai laluan yang jelas untuk mencipta imej Docker untuk aplikasi Go anda menggunakan teknik seperti Binaan Berbilang Peringkat, yang mengurangkan saiz imej, memilih imej asas seperti alpine atau scratch untuk meningkatkan keselamatan dan. kecekapan, dan dengan menggunakan Pengakap Docker untuk memantau kelemahan, anda boleh memastikan aplikasi anda berjalan dengan cekap dan selamat.

Amalan ini bukan sahaja meningkatkan prestasi teknikal, tetapi juga membawa manfaat langsung kepada kehidupan harian anda dan kepada syarikat, menjimatkan masa dan sumber.

Jadi pada kali seterusnya anda membina imej Docker, ingatlah strategi ini. Gunakannya dan perhatikan hasilnya. ?

Atas ialah kandungan terperinci Go + Docker: Cara mencipta imej Docker terbaik untuk aplikasi Golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel sebelumnya:Cara menggunakan go mongoArtikel seterusnya:Cara menggunakan go mongo