Комментарии 26
pprometey, не могли бы вы подробнее рассказать о цели данного контейнера?
Вы делаете контейнер для сборки приложения? Либо же для его запуска?
Если первое, не совсем понятно, зачем вообще нужен контейнер — собрал один раз, сделал пакет (или несколько) и вперед, деплой его налево и направо.
Во втором же случае, у меня такое чувство, что приложение не должно каждый раз собираться заново при развертывании нового контейнера.
Возможно, я не совсем точно понимаю саму суть контейнеризации?
Вы делаете контейнер для сборки приложения? Либо же для его запуска?
Если первое, не совсем понятно, зачем вообще нужен контейнер — собрал один раз, сделал пакет (или несколько) и вперед, деплой его налево и направо.
Во втором же случае, у меня такое чувство, что приложение не должно каждый раз собираться заново при развертывании нового контейнера.
Возможно, я не совсем точно понимаю саму суть контейнеризации?
Я лично его использую для CI\CD на базе Gitlab, т.е. автоматического деплоя.
В целом контейнеры очень удобно как для разработки, так и для дальнейшего развертывания. Особенно когда у тебя крупное приложение состоящее из множества проектов (микросервисная архитектура), использующее различные технологии, и весь этот зоопарк надо заставить слаженно работать. Об этом много написано. Надо немного перестроить мозги, чтобы научится работать с контейнерами. Но как «вкуришь», дальнейшей жизни без них уже просто не представляешь. Это чертовски удобно.
В целом контейнеры очень удобно как для разработки, так и для дальнейшего развертывания. Особенно когда у тебя крупное приложение состоящее из множества проектов (микросервисная архитектура), использующее различные технологии, и весь этот зоопарк надо заставить слаженно работать. Об этом много написано. Надо немного перестроить мозги, чтобы научится работать с контейнерами. Но как «вкуришь», дальнейшей жизни без них уже просто не представляешь. Это чертовски удобно.
«приложение не должно каждый раз собираться заново при развертывании нового контейнера.»
Оно и не собирается каждый раз. Оно собирается один раз при сборке ОБРАЗА. Который уже множество раз разворачивается как КОНТЕЙНЕР одной командой docker run
Оно и не собирается каждый раз. Оно собирается один раз при сборке ОБРАЗА. Который уже множество раз разворачивается как КОНТЕЙНЕР одной командой docker run
Можно без проблем настроить процесс так, когда не надо пересоздавать образ каждый раз и видеть изменения интерпретируемого кода «на лету». Плюс Visual Studio довольно хорошо умеет работать с контейнерами, отслеживает изменения чтобы не пересоздавать образ с нуля, и позволяет производить отладку в контейнерах тоже.
Хорошая статья!
Два вопроса
1) Как работать с HTTPS redirection в docker?
2) Стоит ли использовать образ alpine для сборки приложения?
Два вопроса
1) Как работать с HTTPS redirection в docker?
2) Стоит ли использовать образ alpine для сборки приложения?
Спасибо за положительный отзыв.
1. Подключить папку с сертификатом в контейнеру как volumes. и без проблем. Все прекрасно работает.
Но я использую Traefik — превосходный обратный прокси-сервер и балансировщик для облачной инфраструктуры. Сами контейнеры работают на 80 порту, без https, а вот traefik автоматически получает и продлевает Letsencrypt сертификаты и расшаривает эти контейнеры для мира уже по https.
2. Я стараюсь именно alpine образ и использовать везде, где это только можно, как наиболее легковесный.
1. Подключить папку с сертификатом в контейнеру как volumes. и без проблем. Все прекрасно работает.
Но я использую Traefik — превосходный обратный прокси-сервер и балансировщик для облачной инфраструктуры. Сами контейнеры работают на 80 порту, без https, а вот traefik автоматически получает и продлевает Letsencrypt сертификаты и расшаривает эти контейнеры для мира уже по https.
2. Я стараюсь именно alpine образ и использовать везде, где это только можно, как наиболее легковесный.
В итоговом образе конечно не должно быть ноды. Ангуляр приложение — это скомпилированная статика, которая раздается веб сервером и делает вызовы к АПИ, для какой цели нам там нода?
Надо взять контейнер с нодой, сбилдить в нем ангуляр приложение (АСП для этого не нужен), потом полученную статику переложить в контейнер с веб сервером, который ее будет раздавать — это вообще может быть отдельный контейнер от бекенда. Плюс делаем конейнер с беком (АСП приложением). Можно и объеденить АСП + статику в один контейнер, но тогда деплоиться будут всегди фронт и бек, а это не всегда удобно.
Но золотое правило такое — в итоговых контейнерах не должно быть ничего, кроме минимума необходимого для его работы (например, никаких тулзов для сборки).
Надо взять контейнер с нодой, сбилдить в нем ангуляр приложение (АСП для этого не нужен), потом полученную статику переложить в контейнер с веб сервером, который ее будет раздавать — это вообще может быть отдельный контейнер от бекенда. Плюс делаем конейнер с беком (АСП приложением). Можно и объеденить АСП + статику в один контейнер, но тогда деплоиться будут всегди фронт и бек, а это не всегда удобно.
Но золотое правило такое — в итоговых контейнерах не должно быть ничего, кроме минимума необходимого для его работы (например, никаких тулзов для сборки).
Если я правильно понял, то в статье используется multistage-сборка, и там как раз только статика+api.
Бакенд отдельно работает. В отдельном проекте, в отдельном контейнере. Ангулар это статика, но тут речь идет о шаблоне проекта для Visual Studio и когда запускается в среде Development на ветке develop нужен node, чтобы развернуть сервер разработки Angular
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
spa.Options.StartupTimeout = TimeSpan.FromSeconds(60);
}
});
Тогда нужно больше деталей. Для чего нужен приведенный в примере докер файл — для деплоя на тетсинг? Зачем dotnet publish делается в отдельном стейдже? Зачем в контейнере запускать if (env.IsDevelopment()) нельзя ли обойтись без него (запускать тестинг или стейджинг)? Какого размера получется dev контейнер? Нужно ли отдельно запускать RUN npm install angular/cli -g ведь для билда вроде должно быть достаточно RUN npm install, который запускается позже.
Да, все нужно что есть в Dockerfile, без этого в работать не будет при заданных исходных условиях. Единственное, я «подстраховался» с npm install перед rebuild node-sass.
Я использую Git-flow, это ветка develop, автоматически разворачивающаяся на dev сервер. Ветка master полуавтоматически развертывается в продакшн, там все так как говорите, ничего лишнего, без env.IsDevelopment().
Зачем в контейнере запускать if (env.IsDevelopment())
Я использую Git-flow, это ветка develop, автоматически разворачивающаяся на dev сервер. Ветка master полуавтоматически развертывается в продакшн, там все так как говорите, ничего лишнего, без env.IsDevelopment().
Вот только то, что у вас прописано в env.IsDevelopment, не предназначено для сервера, даже для dev-сервера!
Эта штука предназначена исключительно для горячей сборки измененных модулей. Откуда эти самые измененные модули появятся у вас в контейнере?
Предлагаешь всем разработчикам перед каждым пушем в ветку дев, закоментировать эти строки, а после пуша, раскоментировать и работать дальше?
Или есть другие способы решения данной проблемы?
Или есть другие способы решения данной проблемы?
Конечно же другие способы есть! Использовать другое значение ASPNETCORE_ENVIRONMENT на дев-сервере.
Тогда много отладочной информации, например страницы ошибок и т.д будут недоступны на дев сервере, и тестеры не будут получать полной информации об ошибках и по сути не будут работать все ветки кода, с if (env.IsDevelopment()).
Мне тоже кажется вам стоит как-то разделить — Local от Development, и не надо будет ангуляр-нод сервер в контйенер пихать. Например выкатывать можно staging, а локально использовать Development. Я почему-то не могу спать спокойно, когда знаю что в контейнере есть что-то лишнее :)
Да, согласен. Лишнее в контейнере не есть хорошо. Можно решить эту проблему реорганизовав процесс. Я просто не стал дальше заморачиваться. Такой компромисс меня устроил.
Да, вы правы. Я переработал подход и на самом деле в том варианте Docker файл который сейчас — вообще не должен собираться (хотя собирался каким-то чудом и не только у меня одного).
Доработал. Теперь контейнер чистый как детская слеза.
Доработал. Теперь контейнер чистый как детская слеза.
ARG NODE_IMAGE=node:8.12
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY ["AngularWebApp/AngularWebApp.csproj", "AngularWebApp/"]
RUN dotnet restore "AngularWebApp/AngularWebApp.csproj"
COPY . .
WORKDIR "/src/AngularWebApp"
FROM ${NODE_IMAGE} as node-build
WORKDIR /src
COPY AngularWebApp/ClientApp .
RUN npm install
RUN npm run build -- --prod
FROM build AS publish
RUN dotnet publish "AngularWebApp.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
COPY --from=node-build /src/dist ./ClientApp/dist
ENTRYPOINT ["dotnet", "AngularWebApp.dll"]
1. Для чего строка «FROM build AS publish»? Можно же сделать publish прямо в фазе использования образа build, я правильно понимаю?
2. Для чего строка «FROM base AS final»? Можно же в самом конце взять образ runtime, сделать EXPOSE, копирование файлов и установку entrypoint, так?
2. Для чего строка «FROM base AS final»? Можно же в самом конце взять образ runtime, сделать EXPOSE, копирование файлов и установку entrypoint, так?
Я использовал стандартный Docker файл который по умолчанию генерирует Visual Studio. В целом это вопросы к MS. Ну а дальше по старому шаманскому обычаю — работает — не трожь) Единственное — модифицировал его, добавив сборку Angular приложения образом node.
Попробую, спасибо. Посмотрим.
Попробовал. Да действительно. Вы правы. Обновил статью, оптимизировал файл.
Возможно MS генерирует докер-файл с излишней избыточностью для наглядности процесса мультистейдж сборки докер файла. Это мое предположение.
Возможно MS генерирует докер-файл с излишней избыточностью для наглядности процесса мультистейдж сборки докер файла. Это мое предположение.
Так напишите условия таким образом, чтобы они были доступны и работали! Не понимаю, в чем проблема-то?
Спасибо большое. В том числе и благодаря вашим замечаниям я изменил подход и теперь получил в итоге более правильный контейнер, плюс включил поддержку переменных среды. Выше в комментариях я включил обновленный код dockerfile.
Правда пришлось обновить код файла проекта *.csproj, так как шаблон проекта содержал команды на стадии publish, которые используют nodejs, а в версии 2.1 .net core, nodejs был исключен из образа microsoft/dotnet:2.1-sdk используемого для сборки. Подробнее можно прочитать здесь: github.com/aspnet/Announcements/issues/298
Вот только nodejs из образа убрали, а из шаблона проекта забыли.
ARG BUILD_ARGS
RUN npm run build${BUILD_ARGS}
Правда пришлось обновить код файла проекта *.csproj, так как шаблон проекта содержал команды на стадии publish, которые используют nodejs, а в версии 2.1 .net core, nodejs был исключен из образа microsoft/dotnet:2.1-sdk используемого для сборки. Подробнее можно прочитать здесь: github.com/aspnet/Announcements/issues/298
Вот только nodejs из образа убрали, а из шаблона проекта забыли.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Контейнеризация Angular 6 SPA Template ASP .NET Core 2.1 приложения