애플리케이션에 맞는 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
프로덕션에서 실행 중인 '완전한' 이미지가 필요하지 않다는 사실을 아는 사람은 거의 없습니다. 예를 들어, 우리 언어에 대한 모든 패키지, 소스, 확장 및 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"]
젠장 라파, 그런데 "이 두 이미지"로 뭐하는 거야? 먼저 이미지를 빌더로 사용하여 애플리케이션 실행 파일을 생성합니다.
첫 번째 단계(구축 단계):
그럼 첫 번째 단계에서 생성한 실행 파일을 실행하기 위해 더 작은 이미지를 사용합니다.
2단계(최종단계):
실제로 무슨 일이 일어나는지 확인하고 싶다면 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로 갔지만 이미 큰 차이가 있습니다. 그리고 더욱 개선될 수 있나요?
대답은 '예'입니다. 자세한 내용을 살펴보겠습니다
스크래치는 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 이미지를 구축하는 명확한 경로를 갖게 되었습니다. 다단계 빌드와 같은 기술을 사용하여 이미지 크기를 줄이고 알파인 또는 스크래치와 같은 기본 이미지를 선택하여 보안과 효율성을 향상시킵니다. Docker Scout를 사용하여 취약점을 모니터링하면 애플리케이션이 효율적이고 안전하게 실행되는지 확인할 수 있습니다.
이러한 관행은 기술적 성능을 향상시킬 뿐만 아니라 일상생활과 회사에 직접적인 이익을 가져다 주어 시간과 자원을 절약해 줍니다.
따라서 다음에 Docker 이미지를 구축할 때 이러한 전략을 염두에 두세요. 이를 적용하고 결과를 관찰하십시오. ?
위 내용은 Go + Docker: Golang 애플리케이션을 위한 최고의 Docker 이미지를 만드는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!