각 구성 요소의 실행 위치
| Azure 서비스 | 로컬 대체 수단 | 로컬 워크플로 |
|---|---|---|
| Container Apps | 앱 이미지를 사용하는 Docker Compose | 상태 확인과 게시된 포트로 서비스를 함께 실행 |
| Blob Storage | Azurite | 포트 10000에서 로컬 Blob Storage 사용 |
| Azure Functions(컨테이너) | Functions 기본 이미지 | Rosetta로 amd64 Functions 이미지 실행 |
| AKS | kubectl과 k9s로 AKS 연결, 로컬 API는 kwok | 로컬에서 빌드하고 테스트한 뒤 kubectl과 k9s로 클러스터 사용 |
Container Apps: 시뮬레이터 대신 컨테이너 테스트
Container App은 환경 변수, 비밀 정보, 수신 포트, 프로브, 크기 조정 규칙을 갖춘 하나 이상의 컨테이너를 실행합니다. 문제가 발생하는 부분은 컨테이너이며, 같은 이미지를 실행하면 Mac에서도 Azure와 똑같이 작동합니다. 크기 조정 규칙, 수정 버전, 관리 ID는 Azure에 남지만 컨테이너 내부는 모두 로컬에서 테스트할 수 있습니다.
Compose와 Azurite로 Azure Container App의 컨테이너를 로컬에서 실행
- Compose로 앱을 정의하세요. Container App의 각 컨테이너(메인 컨테이너 및 모든 사이드카)마다 Compose 서비스를 작성하고 같은 이미지, 환경 변수, 수신 포트, 상태 프로브를 사용하세요.
- 저장소용 Azurite를 추가하세요.
mcr.microsoft.com/azure-storage/azurite서비스를 추가해 포트 10000(Blob), 10001(Queue), 10002(Table)을 게시하고 앱의 저장소 연결 문자열이 이 서비스를 가리키게 하세요. - 필요한 경우 amd64로 고정하세요. Azure Functions 기본 이미지처럼 arm64 빌드가 없는 이미지를 사용하는 서비스에는
platform: linux/amd64를 설정하세요. Rosetta를 통해 실행됩니다. - 시작하고 기다리세요.
docker compose up -d --wait를 실행합니다. 상태 확인이 설정된 모든 서비스가 정상 상태가 되면 반환됩니다. - 테스트한 뒤 푸시하세요.
localhost에서 앱을 호출합니다. 정상 작동하면az acr login --name REGISTRY로 로그인하고 이미지에 태그를 붙인 뒤 Container Apps 또는 AKS용으로docker push하세요.
services:
web:
image: myregistry.azurecr.io/web:2.1.0
environment:
AZURE_STORAGE_CONNECTION_STRING: >-
DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=REPLACE_WITH_AZURITE_DEV_KEY;BlobEndpoint=http://azurite:10000/devstoreaccount1;
ports: ["8080:8080"]
depends_on: [azurite]
azurite:
image: mcr.microsoft.com/azure-storage/azurite
ports: ["10000:10000", "10001:10001", "10002:10002"] Azurite의 공개된 개발 계정 키는 Microsoft의 Azurite 문서에서 복사하세요. Compose 네트워크 안에서 앱은 서비스 이름(azurite:10000)으로 Azurite에 접근하며, Mac에서는 localhost:10000으로 접근합니다.
Oxcart에서 Azurite 사용
Azurite는 Microsoft의 오픈 소스 Azure Storage 에뮬레이터로, 포트 10000~10002에서 Blob, Queue, Table(Table은 미리 보기)을 제공합니다. Blob 서비스를 시작하고 Mac에서 호출했습니다.
docker run -d -p 10000:10000 mcr.microsoft.com/azure-storage/azurite \
azurite-blob --blobHost 0.0.0.0
curl -i "http://127.0.0.1:10000/devstoreaccount1?comp=list"
# 403 AuthorizationFailure, Server: Azurite-Blob/3.37.0 (expected for an unsigned request) 서명이 없는 요청에 403이 반환되는 것은 정상입니다. 엔드포인트가 실행 중이며 접근 가능하다는 뜻입니다. 개발 연결 문자열을 사용하는 SDK는 요청에 서명합니다.
컨테이너에서 Azure Functions 사용
테스트한 Azure Functions 기본 이미지는 amd64 빌드만 제공하므로 Apple Silicon Mac에서 기본 빌드하면 "no match for platform in manifest"로 실패합니다. linux/amd64로 빌드하고 실행하면 Oxcart가 Rosetta로 실행합니다.
# Dockerfile
FROM mcr.microsoft.com/azure-functions/python:4-python3.12
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
AzureFunctionsJobHost__Logging__Console__IsEnabled=true \
AzureWebJobsFeatureFlags=EnableWorkerIndexing
COPY . /home/site/wwwroot
docker build --platform linux/amd64 -t my-func .
docker run -d --platform linux/amd64 -p 7071:80 my-func
curl localhost:7071/api/hello 실행 결과 HTTP 트리거 함수가 docker run 후 약 13초 만에 x86_64 환경에서 응답했으며, Functions 호스트 로그에는 경로 매핑과 호출 성공이 표시되었습니다. docker run에도 --platform linux/amd64를 전달하세요. 로컬에서 빌드한 amd64 전용 이미지는 플랫폼을 지정해야만 검색됩니다. 이후 Azure Functions Core Tools에서 func azurecontainerapps deploy 또는 func kubernetes deploy로 같은 이미지를 배포할 수 있습니다.
Azure Container Registry로 푸시
az acr login --name myregistry
docker buildx build --platform linux/amd64 --load -t myregistry.azurecr.io/web:2.1.0 .
docker push myregistry.azurecr.io/web:2.1.0 Container Apps 환경 또는 AKS 노드 풀의 아키텍처에 맞춰 빌드하세요. Oxcart에서 다중 플랫폼 이미지를 푸시하는 기능은 지원되지 않으므로 아키텍처별로 태그 하나를 푸시하거나 CI에서 다중 아키텍처 매니페스트를 게시하세요.
Mac에서 AKS 사용
az aks get-credentials --resource-group RG --name CLUSTER로 kubeconfig에 AKS를 추가하면 macOS에서 kubectl과 k9s를 사용할 수 있습니다. Oxcart로 서비스를 로컬 개발하고 같은 이미지를 AKS에 배포하세요. 로컬 API 및 컨트롤러 테스트에는 실제 제어 영역과 시뮬레이션된 노드를 제공하는 kwok을 Oxcart에서 실행할 수 있습니다. 해당 워크플로는 Mac의 Kubernetes 가이드를 확인하세요.
Oxcart에서 실행하는 이유
로컬 테스트는 반복 주기가 짧아야 효과가 있습니다. Oxcart는 docker run --rm에 42 ms, 컨테이너 20개 중지 및 삭제에 77 ms를 기록해 테스트한 세 런타임 중 가장 빨랐습니다. 컨테이너의 아웃바운드 연결은 Mac에서 열기 때문에 Azure 네트워크로 향하는 VPN이나 비공개 엔드포인트 경로도 적용됩니다. Mac의 컨테이너 네트워킹을 확인하세요.
자주 묻는 질문
Azure Container Apps용 로컬 에뮬레이터가 있나요?
2026년 10월 기준 Microsoft 문서에서 공식 로컬 Container Apps 에뮬레이터는 찾지 못했습니다. Microsoft는 로컬 소스 배포에 az containerapp up을, 로컬 오케스트레이션에 Aspire를 안내합니다. Container App은 컨테이너의 집합이므로 실용적인 로컬 대안은 Compose 프로젝트에서 같은 컨테이너를 실행하고 저장소로 Azurite를 사용하는 것입니다.
Azurite는 Apple Silicon Mac에서 실행되나요?
네. Oxcart에서 docker run -d -p 10000:10000 mcr.microsoft.com/azure-storage/azurite azurite-blob --blobHost 0.0.0.0으로 Azurite 3.37.0을 시작했으며, Blob 엔드포인트가 localhost:10000에서 응답했습니다.
Mac의 컨테이너에서 Azure Functions를 실행할 수 있나요?
네. --platform linux/amd64를 사용하세요. 테스트한 Azure Functions Python 기본 이미지(mcr.microsoft.com/azure-functions/python:4-python3.12)에는 arm64 빌드가 없어 기본 빌드는 "no match for platform in manifest"로 실패합니다. Oxcart에서 linux/amd64로 빌드하고 실행하자 Rosetta로 실행되었으며 HTTP 트리거 함수가 localhost에서 응답했습니다.
Mac에서 Azure Container Registry로 어떻게 푸시하나요?
az acr login --name REGISTRY를 실행한 뒤 docker tag와 docker push REGISTRY.azurecr.io/app:TAG를 실행하세요. Oxcart에서 docker login으로 저장한 자격 증명은 macOS 키체인에 보관됩니다.
Mac에서 AKS용으로 어떻게 개발하나요?
Oxcart로 앱과 종속성을 로컬에서 빌드하고 테스트하세요. az aks get-credentials로 kubectl과 k9s를 AKS에 연결하고, Oxcart의 kwok으로 시뮬레이션된 노드가 있는 로컬 Kubernetes API에서 매니페스트를 확인하세요. Mac에서 Kubernetes 사용을 확인하세요.
Cosmos DB 에뮬레이터는 어떤가요?
Microsoft는 Linux 기반 Cosmos DB 에뮬레이터 이미지(vNext, API for NoSQL)를 제공합니다. Oxcart에서는 아직 테스트하지 않았으므로 의존하기 전에 무료 체험 기간에 프로젝트에서 시험하세요.
출처와 측정 방법
- 예제는 2026-10-10에 Oxcart 0.1.2, Mac17,14, macOS 27.2에서 테스트했습니다(Azurite 3.37.0 Blob, linux/amd64로 실행한 Azure Functions Python 4 이미지, Compose).
- Azurite: https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite. Azure Functions Core Tools: https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local. Container Apps(로컬 에뮬레이터를 찾지 못함): https://learn.microsoft.com/en-us/azure/container-apps/quickstart-code-to-cloud. Cosmos DB Linux 에뮬레이터: https://learn.microsoft.com/en-us/azure/cosmos-db/emulator-linux. 2026-10-10 확인.
- 컨테이너 속도: Oxcart 0.1.2, 2026-10-10, Apple M5 Max, CPU 8개 및 12 GiB, 5회 표본의 중앙값. 다른 런타임은 같은 날 앞서 동일한 Mac과 테스트 하네스에서 docker 29.4 클라이언트로 측정했습니다.