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

Fly.io에서 Docker 사용하기

원문 보기 위키 갱신

Fly.io는 Docker 이미지를 VM으로 변환해 전 세계 네트워크에서 앱을 실행합니다. 이 가이드는 이미지와 태그를 다루는 방법, 배포를 빠르게 만들기 위한 사전 빌드, 흔한 문제 해결, Dockerfile 최적화 팁까지 Fly.io에서 Docker를 효과적으로 사용하는 실용적인 안내를 담고 있어요.

출처: 문서

본문

Fly.io는 Docker 이미지를 전 세계 네트워크에서 실행되는 VM으로 변환해 사용자 가까이에서 앱을 실행합니다. 이 글은 Fly.io에서 Docker를 효과적으로 사용하기 위한 실용적인 가이드입니다.

개요

fly launch로 앱을 배포했다면 이미 Fly.io에서 Docker를 사용한 셈이에요. 내부적으로 Fly.io는 배포되는 모든 앱을 Docker 이미지로 빌드합니다. 하지만 중요한 차이가 있어요. Fly.io는 Docker 컨테이너를 실행하지 않습니다. Docker 이미지를 패키징 형식으로 사용할 뿐입니다. 배포되면 앱은 이미지를 풀어낸(unpacked) 경량 VM 안에서 실행됩니다. 이 글은 이것이 무엇을 의미하는지, 이미지와 태그를 다루는 방법, 이미지를 미리 빌드해 배포를 빠르게 하는 방법을 설명합니다.

Fly는 이제 멀티컨테이너 Machine도 지원해요. 더 많은 정보와 사용 사례를 보려면 이 포럼 게시물과 이 가이드를 확인해 보세요.

왜 알아야 할까요?

Docker 이미지가 Fly.io에서 어떻게 작동하는지 이해하면 더 빠른 배포, 더 나은 이미지 재사용, 앱 수명주기에 대한 더 많은 제어를 얻을 수 있어요. 대규모 빌드를 실행하거나, 같은 앱을 여러 Fly 앱에 배포하거나, 까다로운 릴리스 문제를 디버깅한다면 Docker 이미지에 능숙해지는 것이 큰 도움이 됩니다.

Docker 이미지가 Fly.io에서 작동하는 방식

Fly.io에 배포하면 여러분의 Docker 이미지를 가져와 가상 머신용 루트 파일시스템으로 풀어냅니다. 그게 전부예요. Docker 데몬도, 컨테이너도 없습니다. 그저 경량 VM 안에서 실행되는 여러분의 앱뿐이에요.

부팅 시 각 Fly.io 머신은 환경을 설정하고 Dockerfile의 ENTRYPOINT와 CMD에 설정한 것을 시작하는 최소한의 init 프로세스를 실행합니다. 앱이 종료되면 VM도 종료됩니다.

파일시스템은 휘발성(ephemeral)이에요. 앱이 파일을 쓰거나, 패키지를 설치하거나, 런타임에 무엇이든 수정하면 해당 변경 사항은 머신이 중지될 때 사라집니다. 다음 부팅 시에는 깨끗한 이미지로 돌아갑니다. 데이터를 유지하고 싶나요? 볼륨을 마운트하세요.

더 빠른 배포를 위한 사전 빌드

기본적으로 fly deploy는 빌드와 배포를 한 단계로 수행합니다. Dockerfile이 많은 작업을 한다면 느릴 수 있어요. 자주 배포한다면 빌드를 릴리스와 분리하는 것이 도움이 됩니다.

fly deploy --build-only --push

이 명령은 이미지를 빌드하고 레지스트리에 푸시하지만 배포하지는 않아요.

준비가 되면 미리 빌드한 이미지를 다음과 같이 배포합니다.

fly deploy --image registry.fly.io/myapp:your-tag-here

이렇게 하면 배포 시간에서 귀중한 몇 초(또는 몇 분)를 절약하고, 빌드와 릴리스를 별개의 단계로 취급할 수 있어요.

이미지 태그 관리

fly deploy를 실행하면 Docker 이미지를 빌드하고 Fly.io의 프라이빗 레지스트리로 푸시합니다. 이 이미지는 deployment-20231208-123456 같은 태그를 갖게 됩니다.

같은 이미지를 다시 배포하거나 같은 조직의 다른 앱에 배포하려면 명시적으로 참조할 수 있어요.

fly deploy --image registry.fly.io/myapp:deployment-20231208-123456

더 친숙한 태그를 원한다면 --image-label 플래그를 사용하세요.

fly deploy --image-label my-cool-feature-abc123

나중에 위에서 본 것처럼 --image로 다시 배포할 수 있어요. 카나리 배포나 같은 이미지를 스테이징과 프로덕션으로 승격할 때 특히 유용합니다.

이미지를 수동으로 관리하고 싶다면 Docker 클라이언트를 인증하세요.

fly auth docker

이렇게 하면 표준 Docker 명령으로 이미지를 태그, 푸시, 풀할 수 있어요.

흔한 Docker 이미지 문제 해결

  • 앱이 데이터를 쓰는데 재시작 후 사라져요!
    그건 예상된 동작이에요. Fly.io Machines는 시작할 때마다 루트 파일시스템을 초기화합니다. 영속성이 필요하다면 볼륨을 사용하세요.
  • 배포가 왜 느리죠?
    빌드와 배포 단계를 분리하세요. fly deploy --build-only --push를 실행한 뒤 fly deploy --image로 매번 다시 빌드하지 않도록 하세요.
  • 이상한 빌드 오류가 나요.
    로컬 Docker 데몬으로 빌드하려면 fly deploy --build-local을 사용하세요. 원격 빌드보다 디버깅하기 쉬운 경우가 많아요. 아니면 그냥 일반 Docker를 쓰세요. docker build -t myapp .로 로컬에서 빌드하고 docker run으로 배포 전에 이미지를 테스트하세요.
  • 이미지는 잘 빌드되는데 런타임에서 실패해요.
    ENTRYPOINT와 CMD를 확인하세요. 앱은 Docker 컨테이너가 아니라 VM에서 PID 1로 실행됩니다. 조사하려면 fly logs를 사용하세요. 배포 전에 로컬에서 docker run으로 이미지를 실행해 런타임 문제를 발견할 수도 있어요.
  • 이미지가 다른 앱에 제대로 배포되지 않아요.
    두 앱이 모두 같은 Fly.io 조직에 있는지 확인하고, Fly 레지스트리의 전체 태그를 참조하세요.
  • 앱이 시작 시 크래시하거나 이상하게 동작해요. 무슨 일이죠?
    Fly.io는 기본적으로 앱을 시작하기 전에 준비(readiness) 검사를 실행하지 않아요. 앱이 데이터베이스나 외부 서비스 같은 것에 의존한다면, 작업을 시작하기 전에 그 서비스가 준비될 때까지 기다리도록 해야 합니다. 이를 원활하게 처리하려면 재시도나 시작 로직을 추가하세요. 로그가 여러분의 친구예요. 별도 콘솔에서 fly logs를 실행해 앱이 시작 시 무엇을 하는지/말하는지 확인해 보세요.
  • 로컬에서는 되는데 프로덕션에서 안 돼요.
    그건 아마 "내 머신에서는 실행된다"는 뜻이지 "배포하는 이미지가 제대로 실행된다"는 뜻이 아니에요. docker build로 이미지를 로컬에서 빌드하고 docker run으로 테스트하세요. 그것이 보통 누락된 파일, 잘못된 가정, 환경 불일치를 가장 빨리 발견하는 방법입니다. 또한 기본 이미지를 고정(pin)하고, .dockerignore를 점검하며, 앱에 필요한 모든 것이 이미지에 실제로 포함되어 있는지 확인하세요.

Dockerfile 최적화 팁

Dockerfile에 몇몇 잘 배치된 변경만으로도 빌드 속도, 런타임 성능, 보안을 크게 개선할 수 있어요.

  • 멀티 스테이지 빌드 사용하기. 한 스테이지에서 코드를 컴파일하고 빌드 전용 의존성을 설치한 뒤, 필요한 것만 더 작은 최종 이미지로 복사하세요.
  • 최소 기본 이미지 선택하기. Alpine, distroless, 또는 Debian/Ubuntu의 slim 변형을 사용해 이미지 크기와 공격 표면을 줄이세요. slim 이미지는 최소주의와 호환성 사이의 좋은 중간 지점을 제공하는 경우가 많아요.
  • 레이어 캐시 활용하기. 자주 바뀌지 않는 단계(시스템 패키지 같은)를 파일 앞부분에 배치하세요.
  • RUN 단계 결합하기. &&를 사용해 명령을 연결해 이미지 레이어를 줄이세요.
  • 설치 후 정리하기. 같은 RUN 블록에서 패키지 캐시와 임시 파일을 제거하세요.
  • .dockerignore 사용하기. 빌드 컨텍스트를 깨끗하게 유지하세요. node_modules, .git, 로그 등을 제외하세요.
  • 이미지 버전 고정하기. latest에 의존하지 말고, 빌드를 일관되게 유지하기 위해 정확한 버전을 지정하세요.
  • 하드코딩된 시크릿 피하기. 런타임 시크릿에는 fly secrets를 사용하세요. 정확히 이 용도로 만들어졌으며 시크릿을 앱 환경에 안전하게 주입해요. 빌드 타임 시크릿(프라이빗 패키지 토큰 같은)에는 빌드 시크릿을 사용해 최종 이미지에 새지 않도록 하세요.
  • 비루트로 실행하기. USER를 사용해 컨테이너 권한을 제한하세요.
  • 취약점 스캔하기. Trivy, Docker Scout 같은 도구가 이미지를 안전하게 유지하는 데 도움을 줘요. 배포된 이미지를 빠르게 CVE 스캔하려면 fly registry vulns -a <app>을 시도해 볼 수도 있어요 (아직 실험적이라는 점만 참고하세요).

이 팁과 관행들은 이미지를 더 작고, 안전하며, 배포를 더 예측 가능하게 만들어 줍니다.

관련 자료

더 알아보기 (Learn more)