Upload
chris-biscardi
View
471
Download
3
Embed Size (px)
Citation preview
DEVELOP AND DEPLOYHASKELL WITH DOCKER
@chrisbiscardi
Eng @docker
JavaScript, Haskell
PROBLEM 1
How do I build this locally?
SOLUTION 1: DOCKERgit clone [email protected]:user/project.git .docker build -t myProject .docker run myProject
SOLUTION 1: DOCKERFILEFROM haskell:7.10
COPY . /opt/my-project
WORKDIR /opt/my-project
RUN cabal update
RUN cabal install
CMD ["my-project"]
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 )
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"]
(NOT) SOLUTION 2
I want to write my application; Not optimizedDockerfiles
from last slideLink to Dockerfile
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
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
PROBLEM 3
Working with Multiple GHCs
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
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
PROBLEM 4
Making it to production
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
SOLUTION 4: OOPSerror while loading shared libraries: libgmp.so.10:cannot open shared object file: No such file or directory
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
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
PROBLEM 5
153.3 MB is too big
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 .
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