haskell-language-dockerfile travis-ci docker

Haskell Dockerfile linter, parser, pretty-printer and EDSL, forked from https://github.com/lukasmartinelli/hadolint.

2 years after


Build Status CircleCI


GH Pages Haddock

Blog Post in Portuguese

Dockerfile linter, parser, pretty-printer and embedded DSL, forked from hadolint.

Published on Hackage as language-dockerfile.

It extends hadolint with the pretty-printer and EDSL for writting Dockerfiles in Haskell.

Parsing files

import Language.Dockerfile
main = do
    ef <- parseFile "./Dockerfile"
    print ef

Parsing strings

import Language.Dockerfile
main = do
    c <- readFile "./Dockerfile"
    print (parseString c)

Pretty-printing files

import Language.Dockerfile
main = do
    Right d <- parseFile "./Dockerfile"
    putStr (prettyPrint d)

Writing Dockerfiles in Haskell

{-# LANGUAGE OverloadedStrings #-}
import Language.Dockerfile
main = putStr $ toDockerfileStr $ do
    from "node"
    run "apt-get update"
    runArgs ["apt-get", "install", "something"]
    -- ...

Using the QuasiQuoter

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes       #-}
import Language.Dockerfile
main = putStr $ toDockerfileStr $ do
    from "node"
    run "apt-get update"
    RUN apt-get update
    CMD node something.js
    -- ...

Templating Dockerfiles in Haskell

{-# LANGUAGE FlexibleContexts  #-}
{-# LANGUAGE OverloadedStrings #-}
import Control.Monad
import Language.Dockerfile
tags = ["7.8", "7.10", "8"]
cabalSandboxBuild packageName = do
    let cabalFile = packageName ++ ".cabal"
    run "cabal sandbox init"
    run "cabal update"
    add cabalFile ("/app/" ++ cabalFile)
    run "cabal install --only-dep -j"
    add "." "/app/"
    run "cabal build"
main =
    forM_ tags $ \tag -> do
        let df = toDockerfileStr $ do
            from ("haskell" `tagged` tag)
            cabalSandboxBuild "mypackage"
        writeFile ("./examples/templating-" ++ tag ++ ".dockerfile") df

Using IO in the DSL

By default the DSL runs in the Identity monad. By running in IO we can support more features like file globbing:

{-# LANGUAGE OverloadedStrings #-}
import           Language.Dockerfile
import qualified System.Directory     as Directory
import qualified System.FilePath      as FilePath
import qualified System.FilePath.Glob as Glob
main = do
    str <- toDockerfileStrIO $ do
        fs <- liftIO $ do
            cwd <- Directory.getCurrentDirectory
            fs <- Glob.glob "./test/*.hs"
            return (map (FilePath.makeRelative cwd) fs)
        from "ubuntu"
        mapM_ (\f -> add f ("/app/" ++ FilePath.takeFileName f)) fs
    putStr str



Related Repositories



:whale: A curated list of Docker resources and projects ...



mal - Make a Lisp ...



a record of ideas ...



A solid language pack for Vim. ...



:art: Light & Dark Vim color schemes inspired by Google's Material Design ...

Top Contributors

lukasmartinelli yamadapc cpennington wfleming Arguggi moshen dtan4 ggreif pdericson pdehaan


-   v1.0 zip tar
-   v0.3.5.0 zip tar
-   v0.3.4.0 zip tar
-   v0.3.3.0 zip tar
-   v0.3.2.0 zip tar
-   v0.3.1.0 zip tar
-   v0.3.0.0 zip tar
-   v0.2.3.0 zip tar
-   v0.2.2.0 zip tar
-   v0.1.2.0 zip tar
-   v0.1.1.0 zip tar