Tworzenie potoku (pipeline) w Azure DevOps, który współpracuje z obrazem Docker na zewnętrznym hoście, to częsty scenariusz pozwalający na elastyczne zarządzanie środowiskami i wdrożeniami. Można to osiągnąć na kilka sposobów, w zależności od konkretnych potrzeb – czy chcesz uruchomić zadania potoku w specyficznym kontenerze, czy też wdrożyć aplikację na zdalnym serwerze Docker.
container
w pliku YAML potoku pozwala na wykonywanie zadań wewnątrz kontenera pobranego z określonego obrazu Docker.Istnieją dwie główne metody integracji potoków Azure DevOps z obrazami Docker na zewnętrznych hostach:
Ta metoda jest idealna, gdy środowisko wykonawcze Twojego potoku (np. do budowania, testowania) wymaga specyficznych narzędzi lub konfiguracji dostępnych w niestandardowym obrazie Docker. Obraz ten może być przechowywany w zewnętrznym rejestrze (prywatnym lub publicznym).
Aby Azure DevOps mógł pobrać obraz z zewnętrznego rejestru (np. Azure Container Registry (ACR), prywatnego Docker Hub, innego rejestru), musisz skonfigurować Połączenie Usługi (Service Connection):
W pliku azure-pipelines.yml
zdefiniuj zadanie (job), które ma być uruchomione w kontenerze:
pool:
vmImage: 'ubuntu-latest' # Agent hostujący (może być też self-hosted)
resources:
containers:
- container: my_container_alias # Alias kontenera
type: ACR # Typ rejestru (ACR, Docker Hub, etc.)
azureSubscription: 'MyAzureSubscriptionServiceConnection' # Opcjonalne dla ACR
resourceGroup: 'MyResourceGroup' # Opcjonalne dla ACR
registry: 'youracrname.azurecr.io' # Nazwa twojego rejestru
repository: 'your-image-name' # Nazwa repozytorium obrazu
endpoint: 'MyDockerRegistryServiceConnection' # Nazwa połączenia usługi (jeśli nie ACR lub publiczny Docker Hub)
image: 'yourregistry.com/your-image-name:tag' # Pełna nazwa obrazu (alternatywa dla endpoint/registry/repository)
jobs:
- job: BuildInContainer
displayName: 'Build inside custom container'
container: my_container_alias # Użyj zdefiniowanego kontenera
steps:
- script: |
echo "Ten skrypt działa wewnątrz kontenera!"
# Tutaj umieść kroki budowania, testowania itp.
# Masz dostęp do narzędzi zainstalowanych w obrazie Docker.
displayName: 'Run script in container'
Wszystkie kroki (steps
) w ramach zadania BuildInContainer
będą wykonywane wewnątrz kontenera uruchomionego z obrazu yourregistry.com/your-image-name:tag
.
Architektura aplikacji skonteneryzowanej przy użyciu Docker.
To podejście jest stosowane, gdy celem potoku jest wdrożenie lub zarządzanie kontenerami bezpośrednio na konkretnej maszynie zewnętrznej (np. serwerze deweloperskim, maszynie wirtualnej w innej chmurze). Wymaga to zainstalowania agenta Azure DevOps na tym hoście.
# Przykład dla Linuksa
docker run -d --name azdevops-agent \
-e AZP_URL=https://dev.azure.com/YOUR_ORG_NAME \
-e AZP_TOKEN=YOUR_PAT_TOKEN \
-e AZP_POOL=YOUR_AGENT_POOL_NAME \
-e AZP_AGENT_NAME=my-docker-agent \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /path/on/host/_work:/opt/agent/_work \
mcr.microsoft.com/azure-pipelines/agent:latest
Ważne: Montowanie gniazda Docker (-v /var/run/docker.sock:/var/run/docker.sock
) pozwala agentowi (działającemu w kontenerze) na wykonywanie poleceń Docker na hoście. Jest to potężne, ale niesie ze sobą implikacje bezpieczeństwa – kontener agenta zyskuje uprawnienia do zarządzania wszystkimi kontenerami na hoście.
W pliku azure-pipelines.yml
wskaż pulę agentów, w której znajduje się Twój skonfigurowany agent:
pool:
name: 'YOUR_AGENT_POOL_NAME' # Nazwa puli zawierającej agenta na zewnętrznym hoście
Teraz możesz używać kroków script
lub zadania Docker@2
do interakcji z Dockerem na hoście, na którym działa agent.
steps:
- script: |
echo "Running on the external host: $(hostname)"
docker pull yourregistry.com/your-app-image:latest
docker stop my-app-container || true # Zatrzymaj stary kontener, jeśli istnieje
docker rm my-app-container || true # Usuń stary kontener
docker run -d --name my-app-container -p 8080:80 yourregistry.com/your-app-image:latest
displayName: 'Deploy application container on external host'
# Alternatywnie, używając zadania Docker@2 (wymaga Docker Host Service Connection lub wykonania na agencie z dostępem do dockerd)
# - task: Docker@2
# displayName: 'Run image on external host'
# inputs:
# command: 'run'
# # dockerHostEndpoint: 'MyExternalDockerHostConnection' # Jeśli używasz Docker Host Service Connection
# imageName: 'yourregistry.com/your-app-image:latest'
# containerName: 'my-app-container'
# ports: '8080:80'
# # ... inne argumenty 'run'
W tym scenariuszu potok najpierw buduje i wypycha obraz do rejestru (w poprzednim etapie lub zadaniu, zazwyczaj na agencie hostowanym przez Microsoft), a następnie zadanie uruchamiane na agencie self-hosted pobiera najnowszy obraz i uruchamia go na zewnętrznym hoście.
Architektura CI/CD w środowisku hybrydowym z agentami self-hosted.
Poniższa mapa myśli ilustruje główne komponenty i zależności podczas konfiguracji potoku Azure DevOps do pracy z Dockerem na zewnętrznym hoście.
Ten wykres radarowy porównuje dwa główne podejścia ("Zadanie w Kontenerze" vs "Agent Self-Hosted") pod względem kilku kluczowych czynników. Wyższe wartości oznaczają generalnie lepsze dopasowanie do danego kryterium (skala 1-5, gdzie 1=Niska, 5=Wysoka).
Interpretacja: Podejście z agentem self-hosted daje znacznie większą kontrolę nad docelowym hostem i ułatwia lokalne debugowanie, ale może być nieco bardziej złożone w konfiguracji i wymaga starannego zarządzania bezpieczeństwem (zwłaszcza przy montowaniu gniazda Docker). Podejście z zadaniem w kontenerze jest prostsze w konfiguracji dla samego środowiska wykonawczego zadania i oferuje dużą elastyczność środowiska, ale ma ograniczoną kontrolę nad samym hostem agenta.
Poniższy przykład YAML łączy budowanie obrazu, wypychanie go do Azure Container Registry (ACR) i wdrażanie na zewnętrznym hoście za pomocą agenta self-hosted.
trigger:
- main
variables:
# Połączenie usługi do Twojego ACR
dockerRegistryServiceConnection: 'YourACRServiceConnectionName'
# Nazwa Twojego ACR
containerRegistry: 'youracrname.azurecr.io'
# Nazwa repozytorium obrazu w ACR
imageRepository: 'my-app-image'
# Ścieżka do Dockerfile
dockerfilePath: '$(Build.SourcesDirectory)/Dockerfile'
# Tag obrazu (używamy ID buildu dla unikalności)
tag: '$(Build.BuildId)'
# Nazwa puli z agentem self-hosted na zewnętrznym hoście
externalHostAgentPool: 'YourSelfHostedAgentPoolName'
# Nazwa kontenera na zewnętrznym hoście
containerName: 'my-live-app'
stages:
- stage: BuildAndPush
displayName: 'Build and Push Image'
jobs:
- job: Build
displayName: 'Build and Push to ACR'
pool:
vmImage: 'ubuntu-latest' # Użyj agenta hostowanego przez Microsoft do budowania
steps:
- task: Docker@2
displayName: 'Login to ACR'
inputs:
command: 'login'
containerRegistry: $(dockerRegistryServiceConnection)
- task: Docker@2
displayName: 'Build and Push image'
inputs:
command: 'buildAndPush'
repository: $(imageRepository)
dockerfile: $(dockerfilePath)
containerRegistry: $(dockerRegistryServiceConnection)
tags: |
$(tag)
latest
- task: Docker@2
displayName: 'Logout from ACR'
inputs:
command: 'logout'
containerRegistry: $(dockerRegistryServiceConnection)
- stage: DeployToExternalHost
displayName: 'Deploy to External Host'
dependsOn: BuildAndPush # Uruchom ten etap po zakończeniu BuildAndPush
jobs:
- job: Deploy
displayName: 'Deploy Container on External Host'
pool:
name: $(externalHostAgentPool) # Użyj agenta self-hosted
steps:
- script: |
echo "Deploying image $(containerRegistry)/$(imageRepository):$(tag) on host $(hostname)"
# Zaloguj się do ACR (jeśli agent nie ma stałych poświadczeń)
# Możesz użyć <code>docker login
z poświadczeniami z Key Vault lub Service Connection
# Przykład: docker login $(containerRegistry) -u $(ACR_USER) -p $(ACR_PASSWORD)
# Gdzie ACR_USER i ACR_PASSWORD są zmiennymi tajnymi
docker pull $(containerRegistry)/$(imageRepository):$(tag)
echo "Stopping and removing existing container..."
docker stop $(containerName) || true
docker rm $(containerName) || true
echo "Starting new container..."
docker run -d --name $(containerName) \
-p 80:80 \
--restart always \
$(containerRegistry)/$(imageRepository):$(tag)
echo "Deployment complete."
displayName: 'Pull and Run Docker Container'
# env: # Przykład przekazania zmiennych tajnych
# ACR_USER: $(ACRUsernameFromSecretVariable)
# ACR_PASSWORD: $(ACRPasswordFromSecretVariable)
Chociaż ten film koncentruje się na wdrażaniu na Azure App Service, demonstruje kluczowe etapy tworzenia potoku CI/CD w Azure DevOps do budowania obrazu Docker i jego publikacji, co jest fundamentalnym elementem procesu opisanego powyżej.
Ten przewodnik wideo pokazuje krok po kroku, jak wdrożyć aplikację .NET Web App za pomocą Dockera na Azure, w tym konfigurację potoku DevOps.
Poniższa tabela podsumowuje najważniejsze elementy używane podczas konfiguracji potoków Azure DevOps z Dockerem na zewnętrznych hostach.
Komponent | Opis | Kiedy Używać | Przykładowe Użycie w YAML |
---|---|---|---|
Połączenie Usługi (Service Connection) - Docker Registry | Umożliwia bezpieczne uwierzytelnienie i połączenie z rejestrami kontenerów (ACR, Docker Hub, inne). | Do pobierania (pull) i wypychania (push) obrazów z/do prywatnych rejestrów. | endpoint: 'MyDockerRegistryConnection' (w definicji kontenera) lub containerRegistry: 'MyDockerRegistryConnection' (w zadaniu Docker@2). |
Połączenie Usługi (Service Connection) - Docker Host | Umożliwia bezpośrednie połączenie z demonem Docker na zdalnym hoście (wymaga konfiguracji TLS). | Rzadziej używane; alternatywą jest agent self-hosted. Do wykonywania poleceń Docker na zdalnym hoście bez agenta. | dockerHostEndpoint: 'MyExternalDockerHostConnection' (w zadaniu Docker@2). |
Agent Microsoft-Hosted | Agenci zarządzani przez Microsoft, dostępni w chmurze Azure DevOps. | Do zadań budowania, testowania, wypychania obrazów, gdy nie jest wymagany dostęp do specyficznej infrastruktury zewnętrznej. Używany często z podejściem "Zadanie w Kontenerze". | pool: vmImage: 'ubuntu-latest' (lub inne obrazy). |
Agent Self-Hosted | Agent instalowany i zarządzany przez użytkownika na własnej infrastrukturze (fizycznej, wirtualnej, w kontenerze). | Gdy potok wymaga dostępu do zasobów lokalnych, specyficznego oprogramowania na hoście lub bezpośredniego wykonywania poleceń na zewnętrznym hoście Docker. Kluczowy dla podejścia "Wdrożenie na Zewnętrznym Hoście". | pool: name: 'MySelfHostedPoolName' . |
YAML: resources: containers: |
Definiuje alias, obraz i połączenie dla kontenera, który będzie używany do uruchamiania zadań. | W podejściu "Zadanie w Kontenerze". | resources: containers: - container: myalias ... |
YAML: job: container: |
Określa, że kroki danego zadania (job) mają być wykonane wewnątrz zdefiniowanego kontenera. | W podejściu "Zadanie w Kontenerze". | jobs: - job: MyJob container: myalias steps: ... |
Zadanie Docker@2 |
Wbudowane zadanie Azure DevOps do wykonywania typowych operacji Docker (build, push, run, login, logout). | Do standaryzacji operacji Docker w potoku. Może działać na agentach hostowanych i self-hosted. | - task: Docker@2 inputs: command: 'buildAndPush' ... |
Krok script: |
Umożliwia wykonywanie dowolnych poleceń powłoki (bash, PowerShell, cmd). | Do elastycznego wykonywania poleceń, w tym docker pull , docker run , docker compose itp., zwłaszcza na agentach self-hosted. |
- script: 'docker run hello-world' |
docker stop
i docker rm
przed docker run
).docker-compose
na agencie self-hosted. Wykonaj polecenia docker-compose pull
, docker-compose up -d
itp. w kroku script
.