Как докеризовать HTTP-программу Scala и Akka — простой способ

1656521651 kak dokerizovat http programmu scala i akka prostoj sposob

от Мигеля Лопеса

OzmqgiNemC9zfJjIdorBJGpm-xxmXzTcjaR6

Использование Docker сегодня является данностью. В этом учебнике мы расскажем, как научиться докеризировать наши HTTP-приложения Scala и Akka без даже создавая файл Docker самостоятельно.

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

Для автоматизации создания Dockerfile для нашего проекта, мы будем использовать плагин sbt-native-packager.

Вы можете использовать любой проект HTTP Scala или Akka для этого учебника. Мы будем использовать следующее хранилище, не стесняйтесь клонировать его и не забудьте проверить ветку 6.5-testing-directives.

Добавление плагина

Сначала нам нужно добавить плагин к нашему проекту в файле project/plugins.sbt файл. Если файл не существует, нам нужно его создать, а затем добавить следующую строку:

addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.6")

Затем нам нужно включить плагин в нашем build.sbt файл. Добавьте следующую строчку вверху:

enablePlugins(JavaAppPackaging)

Включение этого плагина позволяет нам создать исполняемый файл для нашей программы. Беги sbt stage в корневом каталоге проекта.

Теперь мы можем выполнить нашу программу, запустив ./target/universal/stage/bin/akkahttp-quickstart. Вы должны увидеть a Success! сообщения. Если вы посылаете запрос GET на адрес localhost:9000/todos вы получите пару задач.

jVniXyVNPfmJU9A2DQStDwnbF8NECz032xsA

Докеризация нашей программы

Пора начать играть с Docker.

Давайте начнем с создания файла Docker для нашего приложения. Беги sbt docker:stageпотом беги cat target/docker/stage/Dockerfile чтобы увидеть его содержимое:

FROM openjdk:latestWORKDIR /opt/dockerADD --chown=daemon:daemon opt /optUSER daemonENTRYPOINT ["/opt/docker/bin/akkahttp-quickstart"]CMD []

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

Мы можем создать образ Docker с помощью этого Dockerfile вручную, но есть более удобный способ сделать это. Давай бежать sbt docker:publishLocal. Как следует из названия, он опубликует образ Docker нашей программы в нашем локальном реестре.

Беги docker images и вы должны увидеть следующую запись:

REPOSITORY            TAG     IMAGE ID       CREATED          SIZEakkahttp-quickstart   0.1     d03732dd0854   42 seconds ago   774MB

Теперь мы можем запустить наше приложение с помощью Docker.

Беги docker run akkahttp-quickstart:0.1вы должны увидеть Success! сообщение еще раз.

Но на этот раз, если мы попытаемся запросить нашу программу, мы получим ошибку:

RCytsNfGbtjSz-gywaiAP06joml9gbwl2nOE

Давай бежать docker ps чтобы получить некоторую информацию о нашем запущенном процессе Docker (сокращен вывод):

CONTAINER ID     IMAGE                       PORTS            NAMES9746162d4723     akkahttp-quickstart:0.1                      serene_agnesi

Как видим, нет открытых портов, поэтому нет возможности связаться с нашим приложением.

Программы по умолчанию в Docker запускаются в своей сети. Существует несколько способов разрешить связь между процессами Docker и хост-машиной. Самый простой способ – открыть порт.

Остановите запущенную программу, нажав Ctrl-C или бегом docker stop $CONTAINER_ID.

В этот раз, когда мы его запустим, мы также откроем порт.

docker run -p 9000:9000 akkahttp-quickstart:0.1

Теперь мы можем спрашивать нашу докеризированную программу:

3Wtn42GiMc9VPzZqNW1pJrZhzu39mlmFZcqt

Настройка нашей настройки

Есть несколько вещей, которые мы можем захотеть сделать с текущими настройками:

  • Что делать, если мы хотим другое название изображения?
  • Что делать, если мы хотим использовать другой порт?
  • Можем ли мы иметь более светлый образ?

Давайте рассмотрим эти распространенные случаи использования.

Изменение названия изображения

Если мы заглянем в официальную документацию плагина, то мы увидим, что существует ряд параметров, которые мы можем изменить.

Прочтите и посмотрите, что еще можно настроить.

Чтобы изменить название изображения, мы можем изменить файл packageName имущество в нашей build.sbt файла, добавьте следующую строку после scalaVersion собственность:

packageName in Docker := "dockerised-akka-http"

Давайте снова опубликуем изображение. Беги sbt docker:publishLocal. Мы можем проверить, имеем ли новое изображение, запустив docker images:

REPOSITORY            TAG   IMAGE ID       CREATED          SIZE akkahttp-quickstart   0.1   d03732dd0854   42 minutes ago   774MB dockerised-akka-http  0.1   d03732dd0854   42 minutes ago   774MB

Теперь у нас есть два изображения, оригинальные и новые. Прекрасно!

Смена порта

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

Но это нормально. Поскольку наша программа работает в другой сети, мы можем сравнить другой порт с внутренним портом 9000.

Когда мы указываем флаг -p 9000:9000 мы говорим, что порт 9000 на хост-машине будет сопоставлен с портом 9000 в сети нашего процесса. Давайте попробуем поменять это.

Беги docker run -p 5000:9000 dockerised-akka-http:0.1 чтобы запустить наш новый образ с другим портом.

Мы можем спросить todos чтобы убедиться, что он работает должным образом:

Na3g2v4jd6FRCUrKyR84TR5lHIG6CrjG5BWn

Делаем наш образ более светлым

Для нашего последнего эксперимента мы постараемся сделать наше изображение более светлым. В настоящее время он использует более 700 МБ.

Сначала давайте увеличим версию, чтобы получить другой тэг и сравнить их. Затем добавьте dockerBaseImage := "openjdk:8-jre-alpine" выше, где мы меняем packageName . Наши build.sbt сейчас выглядит так:

enablePlugins(JavaAppPackaging)
name := "akkahttp-quickstart"version := "0.2"scalaVersion := "2.12.6"
dockerBaseImage := "openjdk:8-jre-alpine"packageName in Docker := "dockerised-akka-http"
val akkaVersion = "2.5.13"val akkaHttpVersion = "10.1.3"val circeVersion = "0.9.3"
libraryDependencies ++= Seq(  "com.typesafe.akka" %% "akka-actor" % akkaVersion,  "com.typesafe.akka" %% "akka-testkit" % akkaVersion % Test,  "com.typesafe.akka" %% "akka-stream" % akkaVersion,  "com.typesafe.akka" %% "akka-stream-testkit" % akkaVersion % Test,  "com.typesafe.akka" %% "akka-http" % akkaHttpVersion,  "com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion % Test,  "io.circe" %% "circe-core" % circeVersion,  "io.circe" %% "circe-generic" % circeVersion,  "io.circe" %% "circe-parser" % circeVersion,  "de.heikoseeberger" %% "akka-http-circe" % "1.21.0",  "org.scalatest" %% "scalatest" % "3.0.5" % Test)

Мы используем другой тег openjdk базовое изображение, чтобы указать, что мы хотим использовать alpineкоторый является лёгким дистрибутивом Linux.

Публикуйте изображение, запустив sbt docker:publishLocal. Получите изображение с помощью docker images . Мы видим, что изображение стало светлее:

REPOSITORY             TAG   IMAGE ID       CREATED          SIZE dockerised-akka-http   0.2   4688366e70bb   32 seconds ago   119MB akkahttp-quickstart    0.1   d03732dd0854   2 hours ago      774MBdockerised-akka-http   0.1   d03732dd0854   2 hours ago      774MB

Давайте убедимся, что это все еще работает.

Беги docker run -p 5000:9000 dockerised-akka-http:0.2, учитывая номер тега. Это не работает, мы получаем такую ​​ошибку:

env: can't execute 'bash': No such file or directory

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

Давайте установим bash в наш образ и попробуем еще раз.

Добавьте следующие строки ниже, где мы меняем packageName в нашем build.sbt файл:

import com.typesafe.sbt.packager.docker._dockerCommands ++= Seq(  Cmd("USER", "root"),  ExecCmd("RUN", "apk", "add", "--no-cache", "bash"))

Мы добавляем дополнительные команды в наш Dockefile. Мы меняем пользователя на root чтобы установить пакет, а затем мы устанавливаем bash.

Попробуем снова запустить программу, docker run -p 5000:9000 dockerised-akka-http:0.2. И сейчас работает, здорово!

Если мы проверим изображение еще раз, альпийский-базированный чуть больше, например 10 МБ. Это ничто по сравнению с примерно 770 МБ других.

Установка bash в альпийский это не самое плохое в мире. Некоторые люди все равно добавляют его из-за своих преимуществ и настройки.

Создание Ash-совместимого исполняемого файла

Установка bash на наш образ – это немного обходной путь. Давайте используем дополнительный плагин для создания исполняемого файла, совместимого с Alpine. Спасибо продавцу Muki за то, что он сообщил нам об этом решении!

Согласно официальной документации, нам нужно включить дополнительный плагин AshScriptPlugin.

Изменить build.sbt файл, чтобы включить оба плагина, и удалить предыдущий обходной путь:

enablePlugins(JavaAppPackaging, AshScriptPlugin)
name := "akkahttp-quickstart"version := "0.3"scalaVersion := "2.12.6"
dockerBaseImage := "openjdk:8-jre-alpine"packageName in Docker := "dockerised-akka-http"
val akkaVersion = "2.5.13"val akkaHttpVersion = "10.1.3"val circeVersion = "0.9.3"
libraryDependencies ++= Seq(  "com.typesafe.akka" %% "akka-actor" % akkaVersion,  "com.typesafe.akka" %% "akka-testkit" % akkaVersion % Test,  "com.typesafe.akka" %% "akka-stream" % akkaVersion,  "com.typesafe.akka" %% "akka-stream-testkit" % akkaVersion % Test,  "com.typesafe.akka" %% "akka-http" % akkaHttpVersion,  "com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion % Test,
  "io.circe" %% "circe-core" % circeVersion,  "io.circe" %% "circe-generic" % circeVersion,  "io.circe" %% "circe-parser" % circeVersion,  "de.heikoseeberger" %% "akka-http-circe" % "1.21.0",
  "org.scalatest" %% "scalatest" % "3.0.5" % Test)

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

Беги sbt docker:publishLocalи затем docker run dockerised-akka-http:0.3.

Вы должны увидеть сообщение об успехе и, если вы спросите задания, вы также должны увидеть их. Прекрасно!

Вывод

В этом руководстве мы доправили HTTP-приложение Scala и Akka. Специально для этой программы ничего не было сделано, а это значит, что настройка будет работать почти так, как есть.

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

Нам даже удалось снизить размер изображения почти в семь раз!

Странно, не правда ли?

Если вам понравилось это руководство и вы хотите узнать, как создать API для программы Todo, просмотрите наш новый бесплатно конечно! ???

Первоначально опубликовано на www.codemunity.io.

Добавить комментарий

Ваш адрес email не будет опубликован.