company_banner

ASP.NET Core + Docker: готовим вместе

    Мы рады поделиться с вами очередной статьей из серии статей о платформе ASP.NET Core (ранее ASP.NET 5). В этот раз Вячеслав Бобик — .NET-разработчика из компании Radario, продолжит свой рассказ о платформе рассказом про применение ASP.NET с контейнерами Docker. Все статьи цикла вы всегда можете найти тут #aspnetcolumn — Владимир Юнев

    image

    Кам нам известно, ASP.NET Core, можно(и даже нужно) запускать не только на Windows, но так же на Mac и Linux. Что это нам дает? Например можем запаковать наше приложение со всеми его зависимостями в docker контейнер и удобно разворачивать его на тестовых\рабочих средах. Мы не будем рассматривать о том что такое docker и как его устанавливать, а вместо этого попробуем собрать образ с ASP.NET Core.

    Подготавлием тестовое приложение


    У нас есть выбор на чем запускать наше первое ASP.NET Core приложение: на mono или на coreclr. Я выберу второй вариант, так как это модно, стильно, молодежно.

    По традиции созданим пустой ASP.NET Core проект:

    alt

    После создания зайдем в файл project.json, он должен содержать следующие поля:

    ....
     "dependencies": {
        "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
        "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final"
      },
    
      "commands": {
        "web": "Microsoft.AspNet.Server.Kestrel --server.urls http://*:5004"
      } ,
    ....

    Нас интересует секция commands, а именно команда web. При её выполнении запускается kestrel вэб сервер, который будет доступен по 5004 порту.(???)

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

    Выполняем


    dnvm list

    alt

    Если у вас выбрана версия с рантаймом clr, то необходимо переключится на coreclr командой:

    dnvm use 1.0.0-rc1-final -r coreclr -p

    Если у вас отсутствует версия coreclr, то её легко установить выполнив

    dnvm upgrade -r coreclr

    Давайте уже запускать наше приложение: перейдем в папку где его создали и выполним.

    > dnu restore
    > dnx web

    Первая команда устанавливает зависимости, вторая собсвенно запускает наше приложение. Теперь если перейдем по адресу http://localhost:5004, то увидим приветственное сообщение. Все, мы готовы паковать наше приложени в контейнер.

    Создаем докер образ


    Для того чтобы докер собрал нам образ(image), нам надо рассказать ему[докеру] как это сделать по средством комманд записанных в докер файле.

    Докер создает обзар(image) читая команды из Dockerfile. Создами Dockerfile в корне проекта (хоть это и не много противоречит лучшим практикам по написанию Dockerfile) содержащего команды:

    FROM microsoft/aspnet:1.0.0-rc1-update1-coreclr
    
    COPY . /app
    WORKDIR /app
    RUN ["dnu", "restore"]
    
    EXPOSE 5004
    ENTRYPOINT ["dnx", "-p", "project.json", "web"]

    FROM — Указываем базовый образ на основе которого мы будем строить собственный
    COPY — Копируем все из папки (.) в файловую систему контейнера, в папку /app
    WORKDIR — Задаем рабочую папку относительно которой будут выполнятся команды RUN, CMD, ENTRYPOINT, COPY и ADD следующите за этой командой в докерфайле

    RUN — Устанавливаем все зависимости для нашего приложения. RUN делаеть чуть больше, чем просто вылонение команды, вот тут описано подробнее
    EXPOSE — Говорим докеру, что в нашем образе есть сервис который будет слушать 5004 порт (который мы указали в файле project.json)

    ENTRYPOINT — Указываем команду которая выполнится при старте контейнера. Отличия от CMD

    Теперь соберем наш образ:

    docker build -t first-aspnet-app .

    Через некоторое время, когда наш образ собрался, запустим его:

    docker run -d -p 80:5004 first-aspnet-app

    -d — переключает запущенный контейнер в бэкграунд, иначене ввод/вывод вэб сервера был бы приаттачен к нашему шеллу.
    -p — маппит порт хостовой машины на exposed порт контейнера. Т.е все запросы пришедшие на 80 порт будут проброшены на порт 5004

    Теперь если пройти по адресу http://localhost:80 мы увидим приветственное сообщение. Так как я с докером работаю в windows среде, то взаимодействую не напрямую, а через docker-machine, поэтому мне надо обраться на ip адресс docker-machine, который можно узнать не хитрой командой

    docker-machine ip

    В моем случае проверить приложение надо по адресу http://192.168.99.100:80 (80 порт можно и не указывать).

    Вуаля, работает!

    alt

    Создаем правильный докер образ


    Однако не все так гладко, конечно же в докере есть и подводные камни. Один большой такой подводный булыжник это проблема PID 1 или зобми процесс, подробнее тут. Ребята из phusion(создатели phusion passenger) позаботились о нас и сделали образ phusion/baseimage решающий много проблем, который мы и будем использовать для создания образа с ASP.NET Core.

    Методом честного копирования команд из Docker файла от Microsoft полчим свой:

    FROM phusion/baseimage:latest
    
    ENV DNX_VERSION 1.0.0-rc1-update1
    ENV DNX_USER_HOME /opt/DNX_BRANCH
    
    ENV DNX_RUNTIME_ID ubuntu.14.04-x64
    
    RUN apt-get -qq update && apt-get -qqy install unzip curl libicu-dev libunwind8 gettext libssl-dev libcurl3-gnutls zlib1g && rm -rf /var/lib/apt/lists/*
    
    RUN curl -sSL https://raw.githubusercontent.com/aspnet/Home/dev/dnvminstall.sh | DNX_USER_HOME=$DNX_USER_HOME DNX_BRANCH=v$DNX_VERSION sh
    RUN bash -c "source $DNX_USER_HOME/dnvm/dnvm.sh \
        && dnvm install $DNX_VERSION -alias default -r coreclr \
        && dnvm alias default | xargs -i ln -s $DNX_USER_HOME/runtimes/{} $DNX_USER_HOME/runtimes/default"
    
    RUN LIBUV_VERSION=1.4.2 \
        && apt-get -qq update \
        && apt-get -qqy install autoconf automake build-essential libtool \
        && curl -sSL https://github.com/libuv/libuv/archive/v${LIBUV_VERSION}.tar.gz | tar zxfv - -C /usr/local/src \
        && cd /usr/local/src/libuv-$LIBUV_VERSION \
        && sh autogen.sh && ./configure && make && make install \
        && rm -rf /usr/local/src/libuv-$LIBUV_VERSION \
        && ldconfig \
        && apt-get -y purge autoconf automake build-essential libtool \
        && apt-get -y autoremove \
        && apt-get -y clean \
        && rm -rf /var/lib/apt/lists/*
    
    ENV PATH $PATH:$DNX_USER_HOME/runtimes/default/bin
    
    COPY . /app
    WORKDIR /app
    RUN ["dnu", "restore"]
    
    EXPOSE 5004
    ENTRYPOINT ["dnx", "web"]
    

    Что делать даль нам уже известно:

    docker build -t aspnetcore-phusion .

    docker run -d -p 80:5004 aspnetcore-phusion

    Если вы как и я не останавливали контейнер созданный в начале статьи, то докер сообщит нам что 80 порт уже занят:

    docker: Error response from daemon: failed to create endpoint loving_kowalevski on network bridge: Bind for 0.0.0.0:80 failed: port is already allocated.

    Остановим наш ранее запущенный контейнер и запустим новый

    docker stop loving_kowalevski
    docker run -d -p 50:5004 aspnetcore-phusion 

    Каждый раз, когда мы запускаем контейнер докер генерируем ему рандомное имя. Как именно — можно посмотреть тут.

    Заключение


    В этой короткой обзорной статье мы создали пару контейнеров с простым ASP.NET Core приложением. Конечно в реальности приложения обычно сложнее, и контейнеров больше.

    На мой взгляд, приложения ASP.NET Core запускающиеся на coreclr пока еще не production ready, так как не все привычные нам библиотке могу запускаться на coreclr. Например для mongodb еще нет драйвера, а autofac еще в альфе. Конечно, можно найти выход в mono, но мы тут с вами про coreclr. Однако прогресс не стоит на месте, библиотеки портируются, и в скором времени мы увидим настоящие кроссплатформенные приложения на ASP.NET Core.

    Авторам


    Друзья, если вам интересно поддержать колонку своим собственным материалом, то прошу написать мне на vyunev@microsoft.com для того чтобы обсудить все детали. Мы разыскиваем авторов, которые могут интересно рассказать про ASP.NET и другие темы.

    Об авторе


    Бобик Вячеслав


    Разработчик кoмпании Radario

    Анонс! Глубокий интенсив на конференции DevCon 2016


    image

    Мы рады объявить о проведении глубокого интенсив-курса по ASP.NET Core в рамках конференции DevCon 2016. Этот курс будет проходить во второй день конференции и займет полный день конференции в течение 6 часов.

    Разработка современных веб-приложений на открытой платформе ASP.NET 5
    В рамках этого интенсива участники примут участие в увлекательном и полном приключений путешествии, посвященном разработке веб-приложений на новейшей платформе ASP.NET 5. Мы пройдем весь путь от нуля до полноценного приложения, развернутого в облаке. И по дороге участники смогут остановиться для изучения внутреннего устройства ASP.NET, работы с реляционными и NoSQL базами данных с помощью Entity Framework 7, разработки приложений на фреймворке MVC, построении моделей, представлений и бизнес-логики, создании REST API, организации процессов непрерывной разработки и тестирования с помощью Git и Visual Studio Online, а также развертывания с помощью Azure и контейнеров Docker. В конце путешествия все участники пройдут посвящение и станут заслуженными рыцарями ASP.NET.

    Регистрация на конференцию DevCon 2016 уже открыта! Регистрируйтесь здесь.
    Вам интересна тема интеграции с контейнерами?

    Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

    • +21
    • 21,1k
    • 2
    Microsoft 379,91
    Microsoft — мировой лидер в области ПО и ИТ-услуг
    Поделиться публикацией
    Похожие публикации
    Комментарии 2
    • +2
      Кажется в Dockerfile есть проблема. Вы всегда копируете всю директорию проекта, а только после этого пытаетесь восстановить пакеты. Из-за этого, даже при малейших изменениях в одном cs файле, контейнер будет пересобираться. Т.е. вы не будете использовать преимущества кеширования слоев для ускорения сборок.
      Лучше разделить COPY на две части: сначала копируем project.json, затем сделать dnu restore, а уж только после этого делать COPY. /app. Примерно так:

      COPY project.json /app/
      WORKDIR /app
      RUN ["dnu", "restore"]
      COPY . /app
      
      EXPOSE 5004
      ENTRYPOINT ["dnx", "web"]
      • 0
        Спасибо за полезный материал!

        А большое количество неправильно написанных слов — это просто опечатки или такой стиль?

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое