> 백엔드 개발 > Golang > Go + Docker: Golang 애플리케이션을 위한 최고의 Docker 이미지를 만드는 방법

Go + Docker: Golang 애플리케이션을 위한 최고의 Docker 이미지를 만드는 방법

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
풀어 주다: 2024-08-14 22:49:02
원래의
539명이 탐색했습니다.

애플리케이션에 맞는 Docker 이미지를 만들고 있는지 의심해 본 적이 없는 사람이 있을까요? 글쎄요, 저는 이 질문을 여러 번 받았지만 거의 항상 제가 하고 있는 일이 옳은지 그른지 알 수 없었습니다.

그래서 이 기사에서는 Go 애플리케이션을 위한 효율적이고 최적화된 Docker 이미지를 생성하기 위한 고급 사례를 살펴보고 알파인 및 스크래치 기본 이미지 사용과 같은 다양한 접근 방식을 비교하고 코드를 통해 각각의 이점을 논의할 것입니다. 사례 및 성능 분석

프로젝트 구조

먼저 컨테이너화된 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
로그인 후 복사

1. Dockerfile 작성

프로덕션에서 실행 중인 '완전한' 이미지가 필요하지 않다는 사실을 아는 사람은 거의 없습니다. 예를 들어, 우리 언어에 대한 모든 패키지, 소스, 확장 및 SDK가 포함된 Ubuntu입니다. 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"]
로그인 후 복사

젠장 라파, 그런데 "이 두 이미지"로 뭐하는 거야? 먼저 이미지를 빌더로 사용하여 애플리케이션 실행 파일을 생성합니다.

첫 번째 단계(구축 단계):

  • 기본 이미지로 golang:1.22-alpine을 사용합니다.
  • 소스코드를 컨테이너에 복사합니다.
  • 종속성을 다운로드하고 Go 애플리케이션 바이너리를 컴파일하세요.

그럼 첫 번째 단계에서 생성한 실행 파일을 실행하기 위해 더 작은 이미지를 사용합니다.

2단계(최종단계):

  • alpine:latest를 기본 이미지로 사용합니다. 이 이미지는 훨씬 작고 바이너리를 실행하는 데 필요한 도구만 있으면 됩니다.
  • 이전 단계(빌더)에서 컴파일된 바이너리를 새 이미지에 복사합니다.
  • 애플리케이션 실행 명령을 정의합니다.

실제로 무슨 일이 일어나는지 확인하고 싶다면 Docker Desktop 내에서 이미지의 계층 구조를 분석할 수 있습니다. 내부에서 그가 무엇을 사용하는지 볼 수 있습니다:

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

이제 방금 생성한 이미지의 크기도 분석할 수 있습니다. 이 경우 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가지 요소와 연결됩니다.

  • 유연성: 알파인 이미지(~5MB)는 작으며 APK 패키지 관리자를 포함하므로 필요한 추가 종속성을 설치할 수 있습니다.
  • 호환성: 동적 라이브러리를 지원하므로 외부 라이브러리에 의존하는 애플리케이션에 적합합니다.
  • 보안: 정기적으로 업데이트되는 Alpine에는 보안 패치가 포함되어 있어 취약점의 위험이 줄어듭니다.

좋아요. 하지만 동일한 SDK 버전(이 경우 golang:1.22-alpine)을 사용하면 어떻게 될까요? 내 지원서는 얼마나 큽니까?

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

로그인 후 복사

음, 이 경우에는 ~250mb의 이미지로 끝났습니다... 알파인과 비교하면 순전히 ~30mb로 갔지만 이미 큰 차이가 있습니다. 그리고 더욱 개선될 수 있나요?

대답은 '예'입니다. 자세한 내용을 살펴보겠습니다

2. 고급 최적화

2.1 스크래치

스크래치는 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:

  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.

실제 예: Docker Desktop에서 Docker Scout 사용

  1. Docker 데스크탑에 액세스: Docker Desktop을 열고 "이미지" 탭으로 이동합니다. 여기에는 로컬에 있는 모든 이미지 목록이 표시됩니다. 이 예에서는 예로 사용할 수 있는 취약점이 포함된 postgres:16-alpine 이미지를 사용했습니다. Go + Docker: Como criar as melhores imagens Docker para aplicações Golang
  2. 취약성 분석 수행: 분석하고 싶은 이미지를 선택하세요. Docker Scout는 선택한 이미지의 알려진 취약점을 자동으로 표시합니다. 각 이미지 옆에는 해결해야 할 취약점이 있는지 여부를 나타내는 보안 상태 아이콘이 표시됩니다. Go + Docker: Como criar as melhores imagens Docker para aplicações Golang
  3. 취약점 세부정보 보기: 이미지를 클릭하시면 발견된 취약점에 대한 자세한 대시보드를 보실 수 있습니다. 여기에는 영향을 받는 패키지 버전, CVE 설명 및 심각도가 포함됩니다. 또한 스캔 및 변경 기록을 볼 수 있어 시간이 지남에 따라 이미지 보안이 어떻게 발전했는지 추적하는 데 도움이 됩니다. Go + Docker: Como criar as melhores imagens Docker para aplicações Golang
  4. 수정사항 적용: Docker Scout 권장 사항에 따라 패키지를 업데이트하거나, 보다 안전한 기반으로 이미지를 다시 빌드하거나, 기타 완화 조치를 취하도록 결정할 수 있습니다. Dockerfile 또는 CI/CD 파이프라인에 수정 사항을 직접 적용할 수 있습니다. Go + Docker: Como criar as melhores imagens Docker para aplicações Golang

이러한 방식으로 이미지가 프로덕션에 배포되기 전에 취약점을 식별 및 수정하고, 가능한 보안 악용으로부터 보호하고, 운영 효율성을 높이는 사전 예방 기능을 갖게 됩니다. 이것이 무슨 뜻인가요? 취약성 분석을 자동화하여 DevOps 또는 보안 팀이 수동 조사가 아닌 수정 조치에 집중할 수 있습니다.

결론

우리가 살펴본 사례를 통해 이제 Go 애플리케이션용 Docker 이미지를 구축하는 명확한 경로를 갖게 되었습니다. 다단계 빌드와 같은 기술을 사용하여 이미지 크기를 줄이고 알파인 또는 스크래치와 같은 기본 이미지를 선택하여 보안과 효율성을 향상시킵니다. Docker Scout를 사용하여 취약점을 모니터링하면 애플리케이션이 효율적이고 안전하게 실행되는지 확인할 수 있습니다.

이러한 관행은 기술적 성능을 향상시킬 뿐만 아니라 일상생활과 회사에 직접적인 이익을 가져다 주어 시간과 자원을 절약해 줍니다.

따라서 다음에 Docker 이미지를 구축할 때 이러한 전략을 염두에 두세요. 이를 적용하고 결과를 관찰하십시오. ?

위 내용은 Go + Docker: Golang 애플리케이션을 위한 최고의 Docker 이미지를 만드는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿