Создаёт свой образ .NET

Создание образов Запускает образ как контейнер Используйте контейнеры для разработки Настроить CI/CD Разверните свое приложение

Предпосылки

Изучите Руководство по началу работы, чтобы понять концепции Docker.

Обзор

Теперь, когда у нас есть хороший обзор контейнеров и платформы Docker, давайте взглянем на создание нашего первого образа. Образ включает в себя все необходимое для запуска приложения — код или двоичный файл, среду выполнения, зависимости и любые другие необходимые объекты файловой системы.

Для завершения этого урока вам потребуется следующее:

Образец заявления

Для нашего примера приложения давайте создадим простое приложение из шаблона с использованием .NET. Создаёт каталог на локальном компьютере с именем dotnet-docker. Открывает терминал и перейдите в данный каталог. Выполняет следующую команду dotnet new, чтобы создать приложение C# с помощью шаблона веб-приложения ASP.NET Core.

$ mkdir dotnet-docker
$ cd dotnet-docker
$ dotnet new webApp -n myWebApp -o src --no-https

Появится вывод, аналогичный следующему.

The template ASP.NET Core Web App was created successfully.
This template contains technologies from parties other than Microsoft, see https://aka.ms/aspnetcore/6.0-third-party-notices for details.

Команда создаст новый каталог с именем src. Просмотрите каталог src и проверяет его содержимое. Вы должны увидеть следующие каталоги и файлы.

├── Pages
│ ├── Error.cshtml
│ ├── Error.cshtml.cs
│ ├── Index.cshtml
│ ├── Index.cshtml.cs
│ ├── Privacy.cshtml
│ ├── Privacy.cshtml.cs
│ ├── Shared
│ ├── _ViewImports.cshtml
│ └── _ViewStart.cshtml
├── Program.cs
├── Properties
│ └── launchSettings.json
├── appsettings.Development.json
├── appsettings.json
├── myWebApp.csproj
├── obj
│ ├── myWebApp.csproj.nuget.dgspec.json
│ ├── myWebApp.csproj.nuget.g.props
│ ├── myWebApp.csproj.nuget.g.targets
│ ├── project.assets.json
│ └── project.nuget.cache
└── wwwroot
├── css
├── favicon.ico
├── js
└── lib

Протестируйте приложение

Давайте запустим наше приложение и убедимся, что оно работает правильно. Открывает терминал, перейдите в каталог src и используйте команду dotnet run.

$ cd /path/to/dotnet-docker/src
$ dotnet run --urls http://localhost:5000

Появится вывод, аналогичный следующему.

Building...
info: Microsoft.Hosting.Lifetime[0]
    Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
    Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
    Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
    Content root path: C:\Users\username\dotnet-docker\src\

Читает выходные данные, чтобы проверяет, как вы можете получает доступ к приложению. В приведённом выше примере Now listening on: http://localhost:5000 указывает, что вы обращаетесь к приложению по адресу http://localhost:5000.

Открывает веб-браузер и получает доступ к приложению на основе URL-адреса в выходных данных. Должна появиться следующая страница.

image of app page

Нажмите Ctrl+C в окне терминала, чтобы останавливает приложение.

Создаёт Dockerfile

В каталоге dotnet-docker\src создаёт файл с именем Dockerfile.

Затем нам нужно добавить строку в наш Dockerfile, которая сообщает Docker, какой образ мы хотели бы использовать для сборки нашего приложения. Открывает Dockerfile в IDE или текстовом редакторе и добавляет следующие инструкции.

# syntax=docker/dockerfile:1

FROM mcr.microsoft.com/dotnet/sdk:6.0 as build-env

Образы Docker могут наследоваться от других образов. Поэтому вместо создания собственного образа мы будем использовать официальный образ .NET SDK, в котором уже есть все инструменты и пакеты, необходимые для создания .NET-приложения.

Мы будем использовать многоэтапную сборку и определим этап для сборки приложения. Мы определяем этап build-env в нашем файле Docker, используя as.

Примечание

Дополнительные сведения о многоэтапных сборках см. в статье Многоэтапные сборки.

Чтобы упростить выполнение остальных наших команд, давайте создадим рабочий каталог для наших исходных файлов. Это указывает Docker использовать данный путь в качестве местоположения по умолчанию для всех последующих команд. При этом нам не нужно вводить полные пути к файлам, но можно использовать относительные пути на основе рабочего каталога.

WORKDIR /src

Хотя это и не обязательно, приведенные далее команды скопируют только файлы csproj, а затем запустят dotnet restore. Каждая команда создаёт новый слой контейнера. Чтобы ускорить создание контейнеров, Docker кэширует данные слои. Поскольку данные файлы не будут часто меняться, мы можем воспользоваться кэшированием, скопировав данные файлы и выполнив восстановление как отдельные команды.

COPY src/*.csproj .
RUN dotnet restore

Затем вам нужно будет копирует остальные исходные файлы в образ. Строка далее скопирует файлы из каталога src на вашем локальном компьютере в каталог с именем src в образе.

COPY src .

Затем вам нужно будет запускает команду dotnet publish для сборки проекта.

RUN dotnet publish -c Release -o /publish

Далее вы укажете образ, который будете использовать для запуска приложения, и определяет его как этап runtime.

FROM mcr.microsoft.com/dotnet/aspnet:6.0 as runtime

Далее указывает рабочий каталог для этого этапа.

WORKDIR /app

Затем копирует каталог/publish из этапа build-env в образ среды выполнения.

COPY --from=build-env /publish .

Открывает порт 80 для входящих запросов.

EXPOSE 80

Теперь все, что нам нужно сделать, это сообщить Docker, какую команду мы хотим запускает, когда наш образ выполняется внутри контейнера. Мы делаем это с помощью команды ENTRYPOINT.

ENTRYPOINT ["dotnet", "myWebApp.dll"]

Вот полный Dockerfile.

# syntax=docker/dockerfile:1

FROM mcr.microsoft.com/dotnet/sdk:6.0 as build-env
WORKDIR /src
COPY src/*.csproj .
RUN dotnet restore
COPY src .
RUN dotnet publish -c Release -o /publish

FROM mcr.microsoft.com/dotnet/aspnet:6.0 as runtime
WORKDIR /publish
COPY --from=build-env /publish .
EXPOSE 80
ENTRYPOINT ["dotnet", "myWebApp.dll"]

.dockerignore файл

Чтобы сделать построить контекст как можно меньше, добавляет .dockerignore файл в папку dotnet-docker и копирует в нее следующее.

**/bin/
**/obj/

Структура каталогов

Напомним, что мы создали каталог на нашем локальном компьютере с именем dotnet-docker и создали простое приложение .NET в папке src. Мы также создали файл Dockerfile, содержащий команды для создания образа, а также файл .dockerignore. Теперь структура каталогов dotnet-docker должна выглядеть так:

├── dotnet-docker
│ ├── src/
│ ├── Dockerfile
│ ├── .dockerignore

Создаёт образ

Теперь, когда мы создали наш Dockerfile, давайте создадим наш образ. Для этого воспользуемся командой docker build. Команда docker build создаёт образы Docker из Dockerfile и «контекста». Контекст сборки — это множество файлов, расположенных по указанному пути или URL-адресу. Процесс сборки Docker может получает доступ к любому из файлов, расположенных в этом контексте.

Команда сборки необязательно принимает флаг --tag. Тег используется для установки имени образа и необязательного тега в формате name:tag. Мы пока не будем использовать необязательный tag, чтобы упростить задачу. Если вы не передаете тег, Docker использует «последний» в качестве тега по умолчанию.

Давайте создадим наш первый образ Docker. Перейдите в каталог dotnet-docker и запускает docker build.

$ cd /path/to/dotnet-docker
$ docker build --tag dotnet-docker .

Просмотр локальных образов

Чтобы увидеть список образов, которые есть на нашем локальном компьютере, у нас есть два варианта. Один из них — использовать CLI, а другой — использовать Docker Рабочий стол. Поскольку сейчас мы работаем в терминале, давайте взглянем на список образов с помощью CLI.

Чтобы просмотреть образы, просто запускает команду docker images.

$ docker images
REPOSITORY      TAG               IMAGE ID       CREATED         SIZE
dotnet-docker   latest            8cae92a8fbd6   3 minutes ago   216MB

Вы должны увидеть хотя бы одно образ в списке, образ, который мы только что создали dotnet-docker:latest.

Тегирование образов

Как упоминалось ранее, имя образа состоит из компонентов имени, разделенных косой чертой. Компоненты имени могут содержать строчные буквы, цифры и разделители. Разделитель определяется как точка, один или два знака подчеркивания или один или несколько дефисов. Компонент имени не может начинаться или заканчиваться разделителем.

Образ состоит из манифеста и списка слоев. На этом этапе не слишком беспокойтесь о манифестах и слоях, за исключением того, что «тег» указывает на комбинацию данных артефактов. Вы можете иметь несколько тегов для образа. Давайте создадим второй тег для созданного нами образа и посмотрим на его слои.

чтобы создать новый тег для образа, которое мы создали выше, выполняет следующую команду.

$ docker tag dotnet-docker:latest dotnet-docker:v1.0.0

Команда docker tag создаёт новый тег для образа. Он не создаёт новый образ. Тег указывает на то же образ и является ещё одним способом ссылки на образ.

Теперь запускает команду docker images, чтобы увидеть список наших локальных образов.

$ docker images
REPOSITORY      TAG               IMAGE ID       CREATED         SIZE
dotnet-docker   latest            8cae92a8fbd6   4 minutes ago   216MB
dotnet-docker   v1.0.0            8cae92a8fbd6   4 minutes ago   216MB

Вы можете видеть, что у нас есть два образа, которые начинаются с dotnet-docker. Мы знаем, что это одно и то же образ, потому что, если вы посмотрите на столбец IMAGE ID, вы увидите, что значения одинаковы для двух образов.

Давайте удалим тег, который мы только что создали. Для этого воспользуемся командой rmi. Команда rmi означает «удаляет образ».

$ docker rmi dotnet-docker:v1.0.0
Untagged: dotnet-docker:v1.0.0

Обратите внимание, что ответ от Docker сообщает нам, что образ не было удалено, а только «не помечено». Вы можете проверяет это, выполнив команду docker images.

$ docker images
REPOSITORY      TAG               IMAGE ID       CREATED         SIZE
dotnet-docker   latest            8cae92a8fbd6   6 minutes ago   216MB

Наше образ с тегом :v1.0.0 было удалено, но тег dotnet-docker:latest все ещё доступен на нашей машине.

Следующие шаги

В этом модуле мы рассмотрели настройку нашего примера приложения .NET, которое мы будем использовать в оставшейся части руководства. Мы также создали файл Dockerfile, который использовали для создания образа Docker. Затем мы рассмотрели тегирование наших образов и удаление образов. В следующем модуле мы рассмотрим, как это сделать:

Запускает образ как контейнер

Обратная связь

Помогите нам улучшить эту тему, оставив свой отзыв. Дайте нам знать, что вы думаете, создав задачу в репозитории Документы Docker GitHub. Или создайте PR, чтобы предложить обновления.