Первоначально опубликовано здесь .
Допустим, мы написали веб -приложение в Haskell.
$ curl http://localhost:8000/hello/World Hello, World! $ curl http://localhost:8000/hello/Haskell Hello, Haskell!
Было бы неплохо, если бы мы могли поделиться этим с другими людьми. Давайте развернуть эту замечательную вещь для Интернет Используя Heroku.
Хаскелл и Никс
Спасибо Nix Использование упаковки Haskell Community Up Bibraries and Executive Armentables очень удобно.
Во -первых, мы сделаем каталог для нашего проекта.
~ $ mkdir haskell-on-heroku ~ $ cd $_ ~/haskell-on-heroku $
Тогда мы можем попросить Cabal, чтобы мы начали с каркаса.
~/haskell-on-heroku $ nix run \ > nixpkgs.cabal-install \ > --command cabal init \ > --minimal \ > --cabal-version=2.4
Наконец, мы добавляем default.nix
который использует Cabal2nix
Анкет
{ haskellPackages ? (import{}).haskellPackages }: haskellPackages .callCabal2nix "haskell-on-heroku" ./. {}
И теперь он готов попробовать.
~/haskell-on-heroku $ nix run \ > --file default.nix \ > env --command cabal new-run # ... Hello, Haskell!
Удивительное веб -приложение
Наш веб -сервер использует изящную библиотеку Haskell Сервер слуги Так что нам нужно добавить это и Варп как зависимость от Haskell-on-heroku.cabal
Анкет
executable haskell-on-heroku main-is: Main.hs build-depends: base >=4.12 && <4.13 + , servant-server + , warp default-language: Haskell2010
Нам, вероятно, также нужно поместить реализацию нашего приложения в Main.hs
Анкет
{-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeOperators #-} {-# OPTIONS_GHC -Wall #-} module Main where import Control.Applicative ((<|>)) import Data.Proxy (Proxy (Proxy)) import Network.Wai.Handler.Warp (run) import Servant ( (:>), Capture, Get, Handler, PlainText, serve, ) import System.Environment (getEnv) type Greeter = "hello" :> Capture "name" String :> Get '[PlainText] String greet :: String -> Handler String greet name = pure $ "Hello, " <> name <> "!" getPort :: IO Int getPort = read <$> getEnv "PORT" <|> pure 8000 main :: IO () main = do port <- getPort run port $ serve (Proxy @Greeter) greet
Развертываемое изображение
Участники сообщества NIX, использующих Docker, сделали создание, совместимые с Docker, из производных NIX очень удобными.
Чтобы попробовать это, поместите следующее в файле где -нибудь, скажем, ~/hello.nix
Анкет
let nixpkgs = import{}; in nixpkgs.dockerTools.buildImage { name = "hello-docker-nix"; tag = "latest"; contents = [ nixpkgs.hello ]; }
Затем построите его.
~ $ nix-build hello.nix
Загрузите результат.
~ $ docker load < result
И наконец запустить это.
~ $ docker run hello-docker-nix:latest hello Hello, world!
Мы можем поместить нашу посылку на докер, совместимый с изображением аналогичным образом. Поместите следующее в файл с именем release.nix
в вашем Haskell-on-heroku
Проектный каталог.
{ nixpkgs ? import{} }: let inherit (nixpkgs) callPackage dockerTools; package = callPackage ./. {}; in dockerTools.buildImage { name = "haskell-on-heroku"; tag = "latest"; contents = [ package ]; }
Используя CALLPACKAGE
Помощник означает, что мы с меньшей вероятностью случайно получим несколько версий набора пакетов NIX. Если это произойдет, наше приложение все равно будет работать нормально, мы просто могли бы получить больше, чем необходимое изображение.
Давайте попробуем построить его и посмотрим, насколько он велик.
~/haskell-on-heroku $ nix-build release.nix # ... build output ~/haskell-on-heroku $ docker load < result 3f5a871dd9ee: Loading layer 38.1MB/38.1MB Loaded image: haskell-on-heroku:latest
Это около 38,1 мегабайт. Это неплохо.
Теперь я собираюсь сэкономить нам некоторые проблемы и добавить Busybox На нашем изображении, а также убедитесь, что у него есть CMD
настроен.
diff --git a/release.nix b/release.nix index 8fa2527..e14a534 100644 --- a/release.nix +++ b/release.nix @@ -3,7 +3,8 @@ let inherit (nixpkgs) callPackage - dockerTools; + dockerTools + busybox; package = callPackage ./. {}; in @@ -12,5 +13,9 @@ in tag = "latest"; contents = [ package + busybox ]; + config = { + Cmd = ["/bin/${package.pname}"]; + }; }
Нам нужно указать команду, чтобы Heroku знал, как запустить контейнер, который он создаст с нашего изображения. Нам нужно Busybox
Потому что Хероку попытается запустить команду нашего изображения с bash -c
Анкет Изображения, построенные с Nix’s Dockertools
настолько минимальны, что у них нет избиение
или даже /bin/sh
.
Отправляя его
Теперь у нас есть все, что нам нужно. Последние шаги — создать приложение Heroku, подтолкнуть наше изображение в реестр Heroku и выпустить его.
Во -первых, предполагая, что у вас уже есть учетная запись Heroku, войдите в командную строку Heroku.
~/haskell-on-heroku $ nix run nixpkgs.heroku \ > --command heroku login
Затем также войдите в реестр контейнеров.
~/haskell-on-heroku $ nix run nixpkgs.heroku \ > --command heroku container:login
Далее создайте приложение.
~/haskell-on-heroku $ nix run nixpkgs.heroku \ > --command heroku create
Создайте наше изображение.
~/haskell-on-heroku $ nix-build release.nix
Загрузите его.
~/haskell-on-heroku $ docker load < result
Отметьте его с помощью имени нашего приложения Heroku и типа процесса, который мы хотели бы запустить его.
~/haskell-on-heroku $ docker tag \ > haskell-on-heroku \ > registry.heroku.com/infinite-anchorage-09330/web
Подтолкнуть его в реестр.
~/haskell-on-heroku $ docker push \ > registry.heroku.com/infinite-anchorage-09330/web
И, наконец, выпустите его.
~/haskell-on-heroku $ nix run nixpkgs.heroku \ > heroku container:release -a infinite-anchorage-09330 web
Эй, Престо, наше удивительное приложение теперь будет доступно всему миру. Как круто.
Однако это похоже на то, что нужно помнить, так что мы лучше всего подчеркиваем это как можно больше в сценарии. Сценарий, который мы могли бы позвонить ./развертывать
.
#!/usr/bin/env bash set -exu app_name=$1 result=$(nix-build --no-out-link release.nix) docker load < $result docker tag $app_name registry.heroku.com/$app_name/web docker push registry.heroku.com/$app_name/web nix run nixpkgs.heroku --command \ heroku container:release -a $app_name web
С этим зданием и развертыванием немного более управляемо.
~/haskell-on-heroku $ ./deploy infinite-anchorage-09330
Я подготовил Репозиторий обо всем, через что мы прошли здесь как ссылка. Если повезет, это может помочь кому -то получить свое потрясающее приложение Haskell на безумное пространство, которое является Интернетом.
Оригинал: «https://dev.to/bradparker/using-nix-to-deploy-a-haskell-web-app-to-heroku-57ob»