У меня есть Azure pipeline
, который выполняет dotnet restore
, dotnet build
и dotnet publish
.
Первоначально мы опубликовали артефакт в Azure App Service
.
Мы хотели бы перейти на Docker
. Поэтому мы начали создавать Dockerfile
и Docker@2 task
в нашем конвейере, который строит изображение и отправляет его в наш Azure Container Registry
.
В большинстве примеров, которые я нахожу, внутри Dockerfile
вам нужно сделать dotnet restore
, dotnet build
и dotnet publish
.
Но если я уже делаю это в своем Azure pipeline
, не могу ли я просто скопировать и вставить свой артефакт из конвейера в образ Docker?
Аналогично этому вопросу: Передайте артефакт в задачу Docker в Azure DevOps А это: Сборка Docker с артефактами в Azure DevOps Pipeline
Я попытался сделать это следующим образом в конце моего конвейера:
- task: Docker@2
inputs:
containerRegistry: '$(containerRegistry)'
repository: '$(imageRepository)'
command: 'buildAndPush'
Dockerfile: '**/Dockerfile'
buildContext: '$(Build.ArtifactStagingDirectory)'
tags: |
$(Build.BuildId)
И мой Dockerfile
, который лежит в основе моего проекта:
FROM mcr.microsoft.com/dotnet/aspnet:8.0
COPY . App/
WORKDIR /App
EXPOSE 80
EXPOSE 443
ENTRYPOINT ["dotnet", "MyApplication.dll"]
Образ правильно создан и опубликован на моем Azure Container Registry
, но когда я пытаюсь запустить его на Docker Desktop
, он сообщает мне, что SDK недоступен на машине. Вот ошибка:
Не удалось загрузить команду, возможно, потому что:
- Вы намеревались выполнить приложение .NET: Приложение «MyApplication.dll» не существует.
- Вы намеревались выполнить команду .NET SDK: Пакеты SDK для .NET не найдены.
Когда я нахожусь в локальной среде, под /bin/Debug...
у меня есть MyApplication.dll
. Поэтому вместо этого я попытался сгенерировать изображение из sdk
:
FROM mcr.microsoft.com/dotnet/sdk:8.0
Но теперь ошибка еще более странная:
Не удалось выполнить, поскольку указанная команда или файл не найдены. Возможные причины этого включают в себя:
- Вы неправильно написали встроенную команду dotnet.
- Вы намеревались выполнить программу .NET, но dotnet-MyApplication.dll не существует.
- Вы намеревались запустить глобальный инструмент, но в PATH не удалось найти исполняемый файл с префиксом dotnet и таким именем.
Я думаю, что мне следует придерживаться образа aspnet
.
Тогда у меня два вопроса: я просто не скопировал (COPY . App/
) в нужное место в Dockerfile
, или в моем Dockerfile
чего-то не хватает для импорта SDK?
Можно ли использовать артефакт, созданный моим конвейером Azure, для создания образа Docker?
Наш конвейер уже настроен и работает хорошо. Меня немного беспокоит включение файла nuget.config
с нашими учетными данными в изображение, чтобы его можно было восстановить с помощью нашего частного канала. Кроме того, мы платим за Azure Container Registry
в зависимости от потребляемой им оперативной памяти и процессора, тогда как Azure Pipeline
бесплатен, поэтому я хочу перенести на него большую часть процесса сборки. Хотя это может быть и не рекомендуется, есть ли способ заставить это работать так, как я пытаюсь достичь?
@Rui Jarimba Мне интересно, почему это рекомендуемый способ сделать это. Можете ли вы уточнить или предоставить документацию по этому поводу? Я изучаю Docker, и любые знания, которые я могу получить, очень приветствуются.
Что касается файла nuget.config
в вашем образе Docker, см. Как добавить частный источник nuget в dotnet dockerfile? . Имейте в виду, что пример образа Docker по ссылке, которую я разместил, использует многоэтапную сборку: часть SDK запускает восстановление, сборку, запуск тестов и, наконец, публикацию приложения; и тогда среда выполнения использует только опубликованные файлы. AFAIK вы платите за хранилище и пропускную способность изображений при использовании ACR, а не ЦП и ОЗУ.
why this is the recommended way to do it
- см. devops.stackexchange.com/questions/5461/…. Поиск в Google тоже поможет :-)
Ниже приведен пример, который я пытаюсь использовать на своей стороне, и он может работать так, как ожидалось. Вы можете обратиться к нему, чтобы попытаться перенастроить конвейер и убедиться, что все необходимые файлы артефактов скопированы в контейнер.
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
EXPOSE 80
EXPOSE 443
COPY . .
RUN dotnet myApp.dll
ENTRYPOINT ["dotnet", "myApp.dll"]
# azure-pipelines.yml
pool:
vmImage: ubuntu-latest
steps:
- task: DotNetCoreCLI@2
displayName: 'dotnet restore'
inputs:
command: restore
projects: myApp.sln
vstsFeed: 'myFeed'
- task: DotNetCoreCLI@2
displayName: 'dotnet build'
inputs:
projects: myApp.sln
arguments: '--no-restore -c Release'
- task: DotNetCoreCLI@2
displayName: 'dotnet publish'
inputs:
command: publish
publishWebProjects: false
projects: myApp.sln
arguments: '--no-build -c Release -o "$(Build.ArtifactStagingDirectory)"'
zipAfterPublish: false
modifyOutputPath: false
- task: CopyFiles@2
displayName: 'Copy Dockerfile'
inputs:
SourceFolder: '$(Build.SourcesDirectory)'
Contents: '**/Dockerfile'
TargetFolder: '$(Build.ArtifactStagingDirectory)'
- task: Docker@2
displayName: 'Build and Push image'
inputs:
containerRegistry: myDockerConnection
repository: myApp
Dockerfile: '**/Dockerfile'
buildContext: '$(Build.ArtifactStagingDirectory)'
tags: |
$(Build.BuildId)
latest
Мне удалось проверить свой образ Docker, используя: docker run --rm -it --entrypoint /bin/sh docker-image
, оказывается, мне нужно добавить zipAfterPublish: false
к моей команде publish
, как вы это сделали. У меня есть похожий Dockerfile
и похожий конвейер, и он работает хорошо. Спасибо!
@M.Ozn, Да, задача dotnet publish
по умолчанию заархивирует файлы артефактов, и в этом случае вам нужно отключить ее, чтобы заархивировать файлы.
Рекомендуемый способ — восстановление и сборка приложения внутри образа Docker. См. Учебник: Контейнеризация приложения .NET.