Heroku에서 마이그레이션하기 (Migrate from Heroku)
이 가이드는 Heroku 앱을 Fly.io로 마이그레이션하는 과정을 순서대로 안내해 드려요. 웹 앱, Postgres, Redis, 백그라운드 워커, 환경 변수, 커스텀 도메인까지 대부분의 앱을 30분 안에 옮길 수 있어요. Heroku의 dyno 기반 요금제와 달리 Fly.io는 실제로 사용한 컴퓨팅, 스토리지, 대역폭만 지불하는 pay-as-you-go 가격 방식을 사용해요.
출처: 문서
본문
이 가이드에서는 Heroku 앱을 Fly.io로 마이그레이션하는 과정을 순서대로 안내해 드려요. 단계를 순서대로 따라 하세요.
이 가이드가 다루는 내용:
- 모든 언어로 된 웹 앱(Node.js, Python, Ruby, Go 등)
- Postgres 데이터베이스
- Redis
- 백그라운드 워커
- 환경 변수
- 커스텀 도메인
소요 시간: 대부분의 앱은 30분 안에 마이그레이션할 수 있어요.
Heroku의 dyno 기반 요금제와 달리 Fly.io는 pay-as-you-go 가격 방식을 사용해요—실제로 사용한 컴퓨팅, 스토리지, 대역폭만 지불하면 돼요. 선택할 수 있는 고정 요금제 티어는 없어요. 현재 요금은 fly.io/pricing에서 확인하세요.
TL;DR - 빠른 경로
경험 많은 개발자를 위한, 전체 마이그레이션을 7개 명령으로 요약한 버전이에요:
# 1. Export secrets (excluding Heroku-managed vars)
heroku config -s -a YOUR_HEROKU_APP | grep -v '^DATABASE_URL\|^REDIS_URL\|^HEROKU_' | sed "s/='\(.*\)'$/=\"\1\"/" > secrets.txt
# ⚠️ Don't commit secrets.txt to git!
# 2. Create Fly app (generates Dockerfile automatically)
cd your-app-directory
fly launch --no-deploy
# 3. Create Managed Postgres and import data
fly mpg create --name your-db --region iad
# ⚠️ Replace CLUSTER_ID below with the cluster ID from the output above.
# If you missed it, run: fly mpg list
fly mpg proxy CLUSTER_ID --local-port 15432 &
pg_dump --no-owner --no-acl "$(heroku config:get DATABASE_URL -a YOUR_HEROKU_APP)" | \
PGPASSWORD=YOUR_FLY_DB_PASSWORD psql -h localhost -p 15432 -U fly-user -d fly-db
fly mpg attach CLUSTER_ID -a your-fly-app
# 4. Import secrets
cat secrets.txt | fly secrets import
# 5. Deploy
fly deploy
# 6. Verify
curl https://your-fly-app.fly.dev
더 자세한 설명은 계속 읽어 보세요.
사전 준비
두 CLI를 모두 설치하세요:
# Install Fly CLI
curl -fsSL https://fly.io/install.sh | sh
# Sign up / log in to Fly
fly auth signup # or: fly auth login
# Make sure you're logged into Heroku
heroku login
1단계: Heroku 구성 내보내기
먼저 Heroku 앱에 대한 모든 것을 캡처해 보세요.
# Set your Heroku app name
export HEROKU_APP="your-app-name"
# Export environment variables (excluding Heroku-managed ones)
heroku config -s -a $HEROKU_APP | grep -v '^HEROKU_' | grep -v '^DATABASE_URL' | grep -v '^REDIS_URL' | sed "s/='\(.*\)'$/=\"\1\"/" > heroku-env.txt
# ⚠️ This file contains secrets - don't commit it to git!
# See what add-ons you have
heroku addons -a $HEROKU_APP
# Check your current process types
heroku ps -a $HEROKU_APP
다음을 기록해 두세요:
- 애드온(Postgres, Redis 등)
- dyno 유형(web, worker 등)
2단계: 앱 준비
앱의 소스 코드가 로컬에 있는지 확인하세요:
# If you don't have it locally, clone from Heroku
heroku git:clone -a $HEROKU_APP
cd $HEROKU_APP
Dockerfile 확인
Fly는 Dockerfile이 있을 때 가장 잘 작동해요. 없다면 괜찮아요—fly launch가 앱 유형에 따라 하나를 생성해 줄 거예요.
Procfile 확인
Heroku Procfile은 Fly 프로세스에 그대로 매핑돼요. 전형적인 Procfile:
web: npm start
worker: npm run worker
release: npm run db:migrate
3단계: Fly에서 Launch
앱 디렉터리에서:
fly launch
이 명령은:
- 앱 유형을 감지해요(Node, Python, Rails 등)
- 필요하면 Dockerfile을 생성해요
fly.toml설정 파일을 만들어요- Postgres 데이터베이스를 프로비저닝할지 물어봐요
프롬프트가 나오면:
- 앱 이름을 선택하세요(또는 생성된 이름을 수락)
- 원하는 리전을 선택하세요
- 데이터베이스가 필요하면 Postgres에 Yes라고 답하세요(완전 관리형 옵션에는 "Managed Postgres" 선택)
- 지금 배포하지 않으려면 No라고 답하세요—시크릿을 설정한 후 배포할 거예요
4단계: 데이터베이스 설정
Heroku Postgres를 사용 중이라면 Fly에 Managed Postgres 클러스터를 만드세요:
fly mpg create --name your-app-db --region iad
출력되는 연결 정보를 저장하세요! 다음과 같은 내용이 보일 거예요:
Connection string: postgresql://fly-user:***@pgbouncer.CLUSTER_ID.flympg.net/fly-db
클러스터 ID(CLUSTER_ID 부분)를 기록해 두세요—다음 몇 개 명령에서 필요해요. 잊어버렸다면 fly mpg list로 언제든 찾을 수 있어요.
데이터를 가져오려면 fly mpg proxy로 로컬 터널을 만든 다음 pg_dump와 psql을 사용하세요:
# Terminal 1: Start a proxy to your Fly database (replace CLUSTER_ID with your cluster ID)
fly mpg proxy CLUSTER_ID --local-port 15432
# Terminal 2: Dump from Heroku and restore to Fly
export HEROKU_DB=$(heroku config:get DATABASE_URL -a $HEROKU_APP)
# Dump the database (plain SQL format)
pg_dump --no-owner --no-acl "$HEROKU_DB" > heroku-dump.sql
# Restore to Fly (via the proxy)
PGPASSWORD=YOUR_PASSWORD psql -h localhost -p 15432 -U fly-user -d fly-db -f heroku-dump.sql
Heroku 전용 확장(pg_stat_statements, event triggers)에 대한 오류가 일부 보일 텐데—이것들은 무시해도 안전해요. 실제 데이터는 성공적으로 가져와져요.
데이터베이스를 앱에 연결하세요:
# Replace CLUSTER_ID with the cluster ID from fly mpg create (or run fly mpg list)
fly mpg attach CLUSTER_ID -a your-app-name
이렇게 하면 앱에 DATABASE_URL이 자동으로 시크릿으로 설정돼요.
5단계: Redis 설정(필요한 경우)
Heroku Redis나 Redis Cloud를 사용한다면:
fly redis create
프롬프트에 따라 진행하세요. 완전 관리형인 Upstash Redis를 사용해요.
생성 후 앱에 연결하세요:
# The create command outputs a REDIS_URL - set it as a secret
fly secrets set REDIS_URL="redis://default:***@fly-your-redis.upstash.io:6379" -a your-app-name
참고: Fly Redis는 기존 데이터 가져오기를 지원하지 않아요. 대부분의 사용 사례(캐싱, 세션)에서는 괜찮아요—캐시가 자연스럽게 워밍업되거든요.
6단계: 환경 변수 가져오기
아까 만든 heroku-env.txt 파일을 기억하시나요? 가져와 보세요:
# Import all your Heroku environment variables
cat heroku-env.txt | fly secrets import -a your-app-name
시크릿이 제대로 가져와졌는지 다시 확인하세요:
fly secrets list -a your-app-name
7단계: 프로세스 구성(Web + Workers)
앱에 여러 프로세스 유형(web + worker)이 있다면 fly.toml을 편집하세요:
[processes]
web = "npm start"
worker = "npm run worker"
# The web process gets the HTTP service
[http_service]
internal_port = 8080
processes = ["web"]
릴리스 명령(데이터베이스 마이그레이션 같은)을 위해 추가하세요:
[deploy]
release_command = "npm run db:migrate"
8단계: 배포
fly deploy
배포를 지켜보세요. 실패하면 로그를 확인하세요:
fly logs
9단계: 앱 검증
# Open your app in a browser
fly apps open
# Check the status
fly status
# View live logs
fly logs
10단계: 도메인 마이그레이션
Heroku에 커스텀 도메인이 있다면:
# Add your domain to Fly
fly certs add yourdomain.com -a your-app-name
# Get the IP addresses to point your DNS to
fly ips list -a your-app-name
DNS를 업데이트하세요:
- 에이펙스 도메인(example.com)의 경우: IPv4 주소를 가리키는 A 레코드를 만드세요.
- 서브도메인(www.example.com)의 경우:
your-app-name.fly.dev를 가리키는 CNAME을 만드세요.
DNS가 전파되면 Fly가 SSL 인증서를 자동으로 프로비저닝해요.
빠른 참조: 명령 매핑
| Heroku | Fly |
|---|---|
heroku apps |
fly apps list |
heroku logs -t |
fly logs |
heroku ps |
fly status |
heroku config |
fly secrets list |
heroku config:set KEY=value |
fly secrets set KEY=value |
heroku run bash |
fly ssh console |
heroku run rails console |
fly ssh console -C "rails console" |
heroku pg:psql |
fly mpg connect CLUSTER_ID |
heroku restart |
fly apps restart |
heroku scale web=2 |
fly scale count web=2 |
흔한 애드온 대체
| Heroku Add-on | Fly Equivalent |
|---|---|
| Heroku Postgres | fly mpg create (Managed Postgres) |
| Heroku Redis / Redis Cloud | fly redis create (Upstash) |
| Heroku Scheduler | Use cron in your app, or a separate "cron" process |
| Papertrail | fly logs built-in, or add a log drain |
| SendGrid | Keep using SendGrid (just use API key) |
| New Relic | Keep using New Relic (just use license key) |
| S3 / Bucketeer | fly storage create (Tigris) or keep using S3 |
| Elasticsearch | Deploy Elasticsearch as a Fly app, or use a hosted service |
| Memcached | Use Redis instead (fly redis create) |
여러 환경(스테이징/프로덕션)
Fly에는 Heroku 같은 "pipeline"이 없어요. 대신 별도의 앱을 만드세요:
# Production
fly launch --name myapp
# Staging
fly launch --name myapp-staging
CI/CD에는 Fly GitHub Action과 함께 GitHub Actions를 사용하세요.
Heroku 종료
Fly에서 모든 것이 작동하면:
- DNS를 Fly로 가리키도록 업데이트하세요.
- DNS 전파를 기다리세요(
dig yourdomain.com으로 확인). - 하루 동안 두 앱을 모니터링해 Heroku로 트래픽이 가지 않는지 확인하세요.
- Heroku dyno를 축소하세요:
heroku ps:scale web=0 worker=0 -a $HEROKU_APP - Heroku 애드온을 취소하세요.
- Heroku 앱을 삭제하세요:
heroku apps:destroy -a $HEROKU_APP