Develop and deploy haskell with docker

21
DEVELOP AND DEPLOY HASKELL WITH DOCKER

Transcript of Develop and deploy haskell with docker

Page 1: Develop and deploy haskell with docker

DEVELOP AND DEPLOYHASKELL WITH DOCKER

Page 2: Develop and deploy haskell with docker

@chrisbiscardi

Eng @docker

JavaScript, Haskell

Page 3: Develop and deploy haskell with docker

PROBLEM 1

How do I build this locally?

Page 4: Develop and deploy haskell with docker

SOLUTION 1: DOCKERgit clone [email protected]:user/project.git .docker build -t myProject .docker run myProject

Page 5: Develop and deploy haskell with docker

SOLUTION 1: DOCKERFILEFROM haskell:7.10

COPY . /opt/my-project

WORKDIR /opt/my-project

RUN cabal update

RUN cabal install

CMD ["my-project"]

Page 6: Develop and deploy haskell with docker

PROBLEM 2

I changed a file...

...and now we're rebuilding the world

Downloading lens-4.11.1...[1 of 1] Compiling Main ( /tmp/lens-4.11.1-7/lens-4.11.1/dist/setup/setup.hs, /tmp/lens-4.11.1-7/lens-4.11.1/dist/setup/Main.o )Linking /tmp/lens-4.11.1-7/lens-4.11.1/dist/setup/setup ...Configuring lens-4.11.1...Building lens-4.11.1...Preprocessing library lens-4.11.1...[ 1 of 82] Compiling Paths_lens ( dist/build/autogen/Paths_lens.hs, dist/build/Paths_lens.o )

Page 7: Develop and deploy haskell with docker

SOLUTION 2: OPTIMIZE THE DOCKERFILEFROM haskell:7.10

RUN apt-get update && \

apt-get install -y libpq-dev

RUN cabal update

RUN mkdir -p /opt/pulsar

WORKDIR /opt/pulsar

RUN mkdir -p /var/log/pulsar

RUN cabal sandbox init

COPY ./pulsar.cabal /opt/pulsar/pulsar.cabal

RUN cabal install --only-dependencies -j4 --allow-newer

COPY ./src /opt/pulsar/src

RUN cabal build

COPY ./snaplets /opt/pulsar/snaplets

COPY ./static /opt/pulsar/static

COPY ./.ghci /opt/pulsar/.ghci

CMD ["/opt/pulsar/dist/build/pulsar/pulsar",\

"--access-log", "/var/log/pulsar/access.log",\

"--error-log", "/var/log/pulsar/error.log"]

Page 8: Develop and deploy haskell with docker

(NOT) SOLUTION 2

I want to write my application; Not optimizedDockerfiles

from last slideLink to Dockerfile

Page 9: Develop and deploy haskell with docker

SOLUTION 2: DOCKER AS ENVgit clone [email protected]:user/my-project.gitdocker run -itv `pwd`:/opt/code --workdir /opt/code haskell:7.10 bash> cabal sandbox init> cabal install --dependencies-only> cabal build> ./dist/build/my-project/my-project

-- later that day

docker run -itv `pwd`:/opt/code --workdir /opt/code haskell:7.10 bash> ./dist/build/my-project/my-project> cabal build> ./dist/build/my-project/my-project

Page 10: Develop and deploy haskell with docker

SOLUTION 2: REASONING

Keeps cabal sandbox on local system (persists betweencontainers)Easy to swap versions:

Universally usable across projects

Distributable, Customizable Environments

docker run -itv `pwd`:/opt/code --workdir /opt/code haskell:7.10 bashdocker run -itv `pwd`:/opt/code --workdir /opt/code haskell:7.8 bash

h() {docker run -itv `pwd`:/opt/code --workdir /opt/code haskell:${1:-7.10} bash}

docker run -itv `pwd`:/opt/code --workdir /opt/code haskell:7.8 bash

Page 11: Develop and deploy haskell with docker

PROBLEM 3

Working with Multiple GHCs

Page 12: Develop and deploy haskell with docker

SOLUTION 3h() {

VERSION=${1-7.10}

docker run -it \

-v `pwd`:/opt/code \

-e CABAL_SANDBOX_CONFIG=/opt/sandbox/docker-sandbox \

-v `pwd`/.sandboxes/$VERSION/:/opt/sandbox/ \

--workdir /opt/code \

haskell:$VERSION bash

}

h

> cabal sandbox init

> cabal install --dependencies-only

> cabal build

Page 13: Develop and deploy haskell with docker

SOLUTION 3: POLISHlocal-repo: /opt/sandbox/packageslogs-dir: /opt/sandbox/logsworld-file: /opt/sandbox/worlduser-install: Falsepackage-db: /opt/sandbox/x86_64-linux-ghc-7.10.1-packages.conf.dbuild-summary: /opt/sandbox/logs/build.log

install-dirs prefix: /opt/sandbox bindir: $prefix/bin libdir: $prefix/lib libsubdir: $abi/$pkgkey libexecdir: $prefix/libexec datadir: $prefix/share datasubdir: $abi/$pkgid docdir: $datadir/doc/$abi/$pkgid htmldir: $docdir/html haddockdir: $htmldir

Page 14: Develop and deploy haskell with docker

PROBLEM 4

Making it to production

Page 15: Develop and deploy haskell with docker

SOLUTION: 4

well, we have a binary...

FROM debian:jessie

COPY ./dist/build/my-project/my-project /opt/my-project/

CMD ["/opt/my-project/my-project"]

docker build -t prod .

docker run -itp 8000:8000 prod

Page 16: Develop and deploy haskell with docker

SOLUTION 4: OOPSerror while loading shared libraries: libgmp.so.10:cannot open shared object file: No such file or directory

Page 17: Develop and deploy haskell with docker

SOLUTION: 4 STATICALLYld-options: -static -pthread

Linking dist/build/my-project/my-project .../opt/ghc/7.10.1/lib/ghc-7.10.1/rts/libHSrts_thr.a(Linker.thr_o): In function `internal_dlopen':(.text+0x245): warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking/opt/ghc/7.10.1/lib/ghc-7.10.1/unix_G4Yo1pNtYrk8nCq1cx8P9d/libHSunix-2.7.1.0-G4Yo1pNtYrk8nCq1cx8P9d.a(HsUnix.o): In function `__hsunix_getpwent':(.text+0xa1): warning: Using 'getpwent' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking/opt/ghc/7.10.1/lib/ghc-7.10.1/unix_G4Yo1pNtYrk8nCq1cx8P9d/libHSunix-2.7.1.0-G4Yo1pNtYrk8nCq1cx8P9d.a(HsUnix.o): In function `__hsunix_getpwnam_r':(.text+0xb1): warning: Using 'getpwnam_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking/opt/ghc/7.10.1/lib/ghc-7.10.1/unix_G4Yo1pNtYrk8nCq1cx8P9d/libHSunix-2.7.1.0-G4Yo1pNtYrk8nCq1cx8P9d.a(HsUnix.o): In function `__hsunix_getpwuid_r':(.text+0xc1): warning: Using 'getpwuid_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking/opt/sandbox/lib/x86_64-linux-ghc-7.10.1/netwo_EyO8YcszhNgAxwqfRy3X8M/libHSnetwork-2.6.2.1-EyO8YcszhNgAxwqfRy3X8M.a(HsNet.o): In function `hsnet_getaddrinfo':(.text+0x21): warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

Page 18: Develop and deploy haskell with docker

SOLUTION: 4 STATIC WORKS

It's a bit ugly, but it works!Really easy to set up

CircleCI, Travis, etcMuch smaller

haskell:7.10706.6 MB

debian:jessie125.2 MB

prod153.3 MB

Page 19: Develop and deploy haskell with docker

PROBLEM 5

153.3 MB is too big

Page 20: Develop and deploy haskell with docker

SOLUTION: MUSLm() {

VERSION=${1-latest}

docker run -it --rm \

-v `pwd`:/opt/code \

-e CABAL_SANDBOX_CONFIG=/opt/sandbox/docker-sandbox \

-v `pwd`/.musl-sandboxes/$VERSION/:/opt/sandbox/ \

--workdir /opt/code \

nilcons/ghc-musl:$VERSION bash

}

docker pull nilcons/ghc-musl

docker build -t alp -f alpine.dockerfile .

Page 21: Develop and deploy haskell with docker

SOLUTION: 5

Much smallerhaskell:7.10 - 706.6 MBdebian:jessie - 125.2 MBprod - 153.3 MBnilcons/ghc-musl - 2.084 GBalpine - 5.254 MB"prod" - 36.94 MB