본문으로 바로가기 본문 바로가기
WIKI 기술 지식 베이스

더 빠른 배포를 위한 베이스 이미지 사용하기

원문 보기 위키 갱신

이 가이드는 더 빠른 배포를 위해 베이스 이미지(base image)를 사용하는 방법을 설명해요. 베이스 이미지는 Dockerfile에서 FROM 줄로 사용하도록 만들어진 이미지예요. 같은 조직의 모든 앱이 다른 앱의 이미지에 접근해 FROM 줄로 쓸 수 있으므로, 두 번째 앱을 만들어 베이스 이미지로 삼는 것이 아주 쉬워요.

출처: 문서

본문

이 가이드는 더 빠른 배포를 위해 베이스 이미지를 사용하는 방법을 설명해요. 베이스 이미지(base image)란 Dockerfile에서 FROM 줄로 사용하도록 만들어진 어떤 이미지든 말해요. Fly.io에 배포된 각 앱은 Fly 레지스트리(registry)에 이미지를 추가할 수 있어요.

같은 조직의 모든 앱은 다른 앱의 이미지에 접근해 Dockerfile의 FROM 줄로 사용할 수 있어요. 이는 두 번째 앱을 만들어 베이스 이미지로 삼는 것만으로 베이스 이미지를 아주 쉽게 만들 수 있다는 뜻이에요.

왜 베이스 이미지를 사용할까?

대부분의 개발자는 프로젝트에서 베이스 이미지를 사용하는 특별한 이유가 있어요. 보통 다음 중 하나예요:

  • 베이스 이미지를 앱의 모든 의존성과 함께 빌드할 수 있어요. 이 베이스 이미지 위에 앱을 다시 빌드하면 배포 과정에서 앱 특유의 빌드 프로세스만 실행되고 의존성 트리 전체를 실행하지 않아요.
  • 같은 앱을 여러 다른 최종 사용자에게 배포해요. 각 최종 사용자는 이미지에 빌드할 몇 가지 특정 파일이나 구성이 있어요. 베이스 이미지는 최종 구성에 거의 도달할 수 있고, 앱이 마지막 단계를 처리해요.

베이스 이미지 만드는 방법

이 가이드는 go-fly-a-site라는 간단한 Go 웹 서버를 실행하는 예시 앱을 빌드하고 배포하는 과정을 안내해요. 앱을 배포한 뒤, 앱 특유의 부분이 아닌 부분에서 베이스 이미지를 만들 거예요. 마지막으로 앱이 그 베이스 이미지를 사용하도록 업데이트할 거예요.

앱 만들기

우리 프로그램은 아주 간단해요. 포트 8080에서 HTTP 요청에 응답하고 "Hello World!"로 응답해요.

package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", HelloServer)
    http.ListenAndServe(":8080", nil)
}

func HelloServer(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello, world!\r\n")
}

Debian 12를 기반으로 Dockerfile을 만들어요. curl과 go를 설치하고, Go 코드를 컴파일하고, 컴파일된 바이너리를 실행하도록 이미지를 구성해요.

FROM debian:12

# Install Go
RUN apt-get update; apt-get upgrade; apt-get -y install golang

# Copy the code for our server to /opt/main.go
COPY main.go /opt/main.go

# Build /opt/server from the code in /opt/main.go
RUN go build -o /opt/server /opt/main.go

# Run our code from main.go as /opt/server
CMD [ "/opt/server" ]

프로젝트 디렉토리에 main.go와 Dockerfile이 있으면 앱을 배포해 보아요:

$ fly launch --name go-fly-a-site --vm-size shared-cpu-1x --no-deploy
....
Your app is ready! Deploy with `flyctl deploy`

이제 추가 파일 fly.toml이 생겼고, go-fly-a-site 앱을 만들었어요.

앱을 배포해 보아요:

$ fly deploy
==> Verifying app config
Validating /Users/fly/Code/go-fly-a-site/fly.toml
✓ Configuration is valid
--> Verified app config
==> Building image
==> Building image with Depot
--> build:
...

Visit your newly deployed app at https://go-fly-a-site.fly.dev/

실행 중인 것을 확인할 수 있어요:

$ curl https://go-fly-a-site.fly.dev/
Hello, world!

이제 앱이 빌드되고 실행되고 있어요. 좋지만, fly deploy할 때마다 apt로 Go를 다시 설치할 수도 있어요. main.go를 업데이트하는 것보다 Go 설치를 훨씬 덜 자주 하고 싶으니, Go를 설치해 주는 베이스 이미지를 만들 수 있어요.

베이스 이미지 만들기

base.Dockerfile이라는 새 파일을 만들어 보아요. 이 파일에서는 Go 설치는 유지할 거예요. 이전 CMD 문을 [ "sleep", "inf" ]로 바꿔서, 나중에 필요하다면 이 이미지에 SSH로 접속해 쉽게 검사할 수 있게 해요.

FROM debian:12

# Install Go
RUN apt-get update; apt-get upgrade; apt-get -y install golang

CMD [ "sleep", "inf" ]

fly.toml을 fly-base.toml로 복사하고 다음 수정을 해 보아요:

  • 앱 이름에 -base를 붙여요.
  • [build] 섹션에 dockerfile을 명시적으로 포함해요.
  • [http_service] 섹션을 제거해요.

결과 파일은 이렇게 생겼어요:

app = 'go-fly-a-site-base'
primary_region = 'lax'

[build]
    dockerfile = "base.Dockerfile"

[[vm]]
  size = 'shared-cpu-1x'

다음 옵션으로 앱을 만들어 보아요:

  • --ha=false는 앱이 단일 Machine을 사용하도록 보장해요.
  • --config base.fly.toml은 올바른 구성 파일을 지정해요.

기존 fly.toml 파일에 대해 물어보면 예(yes)를 선택해 그 구성을 복사해요. 설정을 조정하는 단계는 건너뛸 수 있어요.

$ fly launch --ha=false --config base.fly.toml
An existing fly.toml file was found for app go-fly-a-site-base
? Would you like to copy its configuration to the new app? Yes
Using build strategies '[the "base.Dockerfile" dockerfile]'. Remove [build] from fly.toml to force a rescan
Creating app in /Users/fly/Code/go-fly-a-site
We're about to launch your app on Fly.io. Here's what you're getting:

...
Region:       Los Angeles, California (US) (from your fly.toml)
App Machines: shared-cpu-1x, 256MB RAM     (from your fly.toml)
...

? Do you want to tweak these settings before proceeding? (y/N)
Created app 'go-fly-a-site-base' in organization 'personal'
Admin URL: https://fly.io/apps/go-fly-a-site-base
Hostname: go-fly-a-site-base.fly.dev
Wrote config file base.fly.toml
...
--> build:
--> Building image done
image: registry.fly.io/go-fly-a-site-base:deployment-01JTKF7JXJ1ZGMA76GCJ5WGZQZ
image size: 233 MB

몇 가지 주의할 점이 있어요:

  • 사용할 수 있는 베이스 이미지 이름이 있어요. 바로 image:에 제공된 URL이에요.
  • 관리자 URL로 가면 Registry를 클릭해 같은 이미지 URL을 볼 수 있어요.
  • Registry에는 만들어진 이미지 목록이 있어요.
  • 조직의 어떤 앱이든 Dockerfile의 FROM 문에 이미지 URL을 사용할 수 있어요.
  • 다른 조직의 앱이 이 이미지를 사용하려 하면 오류가 발생해요.

베이스 이미지를 사용하도록 앱 업데이트하기

베이스 이미지를 만든 뒤 go-fly-a-site의 Dockerfile을 업데이트해 보아요:

FROM registry.fly.io/go-fly-a-site-base:deployment-01JTKF7JXJ1ZGMA76GCJ5WGZQZ

# Copy the code for our server to /opt/main.go
COPY main.go /opt/main.go

# Build /opt/server from the code in /opt/main.go
RUN go build -o /opt/server /opt/main.go

# Run our code from main.go as /opt/server
CMD [ "/opt/server" ]

업데이트된 Dockerfile이 있으면 fly deploy로 앱을 배포해 보아요.

$ fly deploy
==> Verifying app config
Validating /Users/fly/Code/go-fly-a-site/fly.toml
✓ Configuration is valid
--> Verified app config
==> Building image
==> Building image with Depot
--> build:
[+] Building 20.7s (8/8) FINISHED
 ...
 => [internal] load metadata for registry.fly.io go-fly-a-site-base:deployment-01JTKF7JXJ1ZGMA76GCJ5WGZQZ
 ...

새 베이스 이미지를 사용했고 앱이 실행 중임을 확인할 수 있어요:

$ curl https://go-fly-a-site.fly.dev/
Hello, world!

베이스 이미지를 위한 Machine 하나를 종료할 수 있어요:

$ fly machine list --config base.fly.toml
1 machines have been retrieved from app go-fly-a-site-base.
View them in the UI here

go-fly-a-site-base
ID           	NAME              	...
d890175f6940e8	wandering-wave-6179	...

Machine ID를 잡아서 앱과 Machine id로 fly machine stop을 실행해 보아요:

$ fly machine stop d890175f6940e8 --config base.fly.toml
Sending kill signal to machine d890175f6940e8...
d890175f6940e8 has been successfully stopped

저장되고 있는 이미지의 루트 파일 시스템 스토리지에 대해서만 비용이 청구돼요.

이제 프로젝트용 베이스 이미지가 생겼어요! Go를 다시 설치하지 않고도 main.go 코드를 수정하고 배포할 수 있어요. 베이스 이미지에 추가 의존성을 더해야 한다면 base.Dockerfile을 수정하고 다시 배포한 뒤, 배포 명령 또는 앱 대시보드의 Registry 섹션에서 새 image:를 얻으면 돼요.

명령 참조

베이스 이미지의 Machine 가져오기: fly machine list --config base.fly.toml

베이스 이미지의 Machine 시작하기: fly machine start <ID_FROM_LIST> --config base.fly.toml

베이스 이미지의 Machine 중지하기: fly machine stop <ID_FROM_LIST> --config base.fly.toml

베이스 이미지에 SSH 접속하기: fly ssh console --config base.fly.toml (Machine이 시작되어 있는지 확인하세요)

베이스 이미지 다시 빌드하기: fly deploy --config base.fly.toml (base.Dockerfile에 변경 사항을 먼저 적용하고, 끝나면 Machine을 중지하는 것을 잊지 마세요)

추가 참고 사항

많은 앱이 사용하게 될 베이스 이미지가 있다면, 그것을 전용 앱 디렉토리에 두는 것이 합리적일 수 있어요. 일반 앱처럼 fly.toml과 Dockerfile을 사용할 수 있어요.

베이스 이미지는 레지스트리에 남아 있어요. 이미지가 Machine과 연결되어 있는 한, 설령 Machine이 중지되어 있어도 삭제되지 않아요.

베이스 이미지의 이미지 레지스트리 URL은 앱의 대시보드 Registry 탭에서, 또는 fly releases --image를 실행해 찾을 수 있어요.

관련 사용 사례

Fly 빌더를 건너뛰고 Docker 도구를 직접 사용해 이미지를 관리하고 싶으신가요? Fly.io 프라이빗 레지스트리로 Docker 이미지 관리하기를 참고해 보아요. Fly.io의 Docker 레지스트리로 이미지를 빌드하고, 푸시하고, 배포하고, 관리하는 방법을 안내하는 가이드예요!

관련 읽을거리

  • Deploy with a Dockerfile Dockerfile에서 앱을 배포하는 방법에 대한 일반 가이드예요. 베이스 이미지를 만들 때 유용한 배경 지식을 제공해요.
  • App Configuration (fly.toml) fly.toml이 빌드, 이미지, 배포를 어떻게 오케스트레이션하는지에 대한 자세한 내용이에요.

더 알아보기 (Learn more)