Giter Club home page Giter Club logo

docker-erlang-example's Introduction

About

This file contains a step-by-step guide that demonstrates how one can create a compact docker image containing a small service written in Erlang. More complex docker examples can be found in the advanced_examples folder.

Create a Docker Image Using Alpine Linux

In this example we create a docker image containing a small Erlang application.

We use the following Dockerfile, containing two build stages:

# Build stage 0
FROM erlang:alpine

# Set working directory
RUN mkdir /buildroot
WORKDIR /buildroot

# Copy our Erlang test application
COPY dockerwatch dockerwatch

# And build the release
WORKDIR dockerwatch
RUN rebar3 as prod release

# Build stage 1
FROM alpine

# Install some libs
RUN apk add --no-cache openssl && \
    apk add --no-cache ncurses-libs && \
    apk add --no-cache libstdc++

# Install the released application
COPY --from=0 /buildroot/dockerwatch/_build/prod/rel/dockerwatch /dockerwatch

# Expose relevant ports
EXPOSE 8080
EXPOSE 8443

CMD ["/dockerwatch/bin/dockerwatch", "foreground"]

The image is built with the following command:

$ docker build -t erlang-dockerwatch .

Notice that if you need a proxy to access the internet, you must forward your proxy settings to docker, for example by giving the option --build-arg https_proxy=$HTTP_PROXY to docker build.

This is what happens:

1. Build stage 0: build

This step starts from the official erlang docker image based on alpine linux. So with the base image, a full Erlang/OTP installation and rebar3 already exists.

Our Erlang application is found in the dockerwatch directory on our local filesystem, and we use the COPY command to import this complete directory into the current working directory in the image.

Finally, we release our erlang application using rebar3 and the following rebar.config.

{deps, [{jsone,  "1.4.7"},   %% JSON Encode/Decode
        {cowboy, "2.5.0"}]}. %% HTTP Server

{relx, [{release, {dockerwatch, "1.0.0"}, [dockerwatch]},
        {vm_args, "config/vm.args"},
        {sys_config, "config/sys.config"},
        {dev_mode, true},
        {include_erts, false},
        {extended_start_script, true}
    ]}.

{profiles, [{prod, [{relx, [{dev_mode, false},
                            {include_erts, true},
                            {include_src, false}]}]}
           ]}.

2. Build stage 1: create a minimal docker image

Now that our application is released, we can discard all extras that was needed for compilation. That is, we no longer need rebar3 or the full Erlang/OTP installation, since our release already contains the required parts of Erlang/OTP, including the runtime system. So, we start a new build stage from the apline linux docker image.

Using the COPY command with option --from=0, we specify that we want to copy artifacts from build stage 0 into the current build stage. We use this to copy our released Erlang application into the final image.

We expose the relevant ports (needed by our application), and specify the command to execute when running the image.

What happened?

$ docker images
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
erlang-dockerwatch   latest              fcdd1aaa2ee7        16 seconds ago      26MB
    ...

The final docker image for the application has a size of approximately 26MB. It may be useful to know that one can get down the image size for this application even further (to approximately 13MB) by using some tricks (e.g., compiling the Erlang release without the ncurses library, stripping away debug symbols from binaries and compressing applications). An alternative docker file, which is named Dockerfile.very_small_image, illustrates how this can be done.

Generating Certificate

Generate certificates in subdirectory ssl.

$ ./create-certs

For some more details of what this command does, see README-CERTS.md

Running the Erlang Application

We start the image in a docker container by issuing the following command.

$ docker run -d -p 8443:8443 --init --volume="$PWD/ssl:/etc/ssl/certs" --log-driver=syslog erlang-dockerwatch
870f979c5b4cdb7a1ba930b020043f50fa7457bf787237706fb27eefaf5fe61d

Let's parse some of the input.

  • -d, starts the container in the background and prints the container ID.
  • -p 8443:8443, exposes port 8443 from the container to our localhost.
  • --init, use the tini initialization as PID 1 in order to prevent zombie processes.
  • --volume="$PWD/ssl:/etc/ssl/certs", mounts our local directory ($PWD/ssl) with certificates to /etc/ssl/certs the container.
  • --log-driver=syslog, will log all data from stdout in the container to our local syslog.

In /var/log/syslog we can see these entries:

Nov  7 14:55:42 elxa19vlx02 NetworkManager[1738]: <info>  [1541598942.5025] device (veth2644103): link connected
Nov  7 14:55:42 elxa19vlx02 NetworkManager[1738]: <info>  [1541598942.5026] device (docker0): link connected
Nov  7 14:55:43 elxa19vlx02 da217065cb2d[1334]: Exec: /dockerwatch/erts-10.1.1/bin/erlexec -noshell -noinput +Bd -boot /dockerwatch/releases/1.0.0/dockerwatch -mode embedded -boot_var ERTS_LIB_DIR /dockerwatch/lib -config /dockerwatch/releases/1.0.0/sys.config -args_file /dockerwatch/releases/1.0.0/vm.args -pa -- foreground
Nov  7 14:55:43 elxa19vlx02 da217065cb2d[1334]: Root: /dockerwatch
Nov  7 14:55:43 elxa19vlx02 da217065cb2d[1334]: /dockerwatch

And here is our docker container:

$ docker ps
CONTAINER ID        IMAGE                COMMAND                  CREATED             STATUS              PORTS                              NAMES
870f979c5b4c        erlang-dockerwatch   "/dockerwatch/bin/do…"   3 minutes ago       Up 2 minutes        8080/tcp, 0.0.0.0:8443->8443/tcp   nifty_heisenberg

Fetch container IP Address from container id:

$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 870f979c5b4c
172.17.0.2

Create a counter called cnt using https with curl:

$ curl --cacert ssl/dockerwatch-ca.pem -i -H "Content-Type: application/json" -X POST -d "" https://localhost:8443/cnt
HTTP/1.1 204 No Content
server: Cowboy
date: Wed, 22 Feb 2017 13:12:54 GMT
content-length: 0
content-type: text/html
vary: accept

Read all counters using https with curl as json:

curl --cacert ssl/dockerwatch-ca.pem -H "Accept: application/json" https://localhost:8443
["cnt"]

Read the counter cnt using https with curl as json:

curl --cacert ssl/dockerwatch-ca.pem -H "Accept: application/json" https://localhost:8443/cnt
{"cnt":0}

Increment the counter cnt using http with curl:

curl -H "Content-Type: application/json" -X POST -d '{}' http://172.17.0.2:8080/cnt

Read the counter cnt using http with curl as text:

curl -H "Accept: text/plain" http://172.17.0.2:8080/cnt
1

Increment the counter cnt by 20 using http with curl:

curl -H "Content-Type: application/json" -X POST -d '{"value":20}' http://172.17.0.2:8080/cnt

Read the counter cnt using http with curl as text:

curl -H "Accept: text/plain" http://172.17.0.2:8080/cnt
21

docker-erlang-example's People

Contributors

aswales avatar bjorng avatar garazdawi avatar kjellwinblad avatar psyeugenic avatar roadrunnr avatar sirihansen avatar stevereaver avatar vkatsuba avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

docker-erlang-example's Issues

minikube-distributed example is too limited

I am currently trying to get an erlang based application running that requires a minimum of about 20 pods.
(sorry I cannot show the code ATM)

The problem is the list of ports that you need to open, configure individually and apply as lmits to each of the kernes. It makes for exeedingly long service and deployment k8s resource statements.

I think the example should at least show how to use this with a HA/load-balancing setup 3 or more backend pods.

Error loading shared library libstdc++.so.6

I followed the readme, but found that when I ran the container I got this error:

$ docker run -p 8080:8080 --rm foo
Error loading shared library libstdc++.so.6: No such file or directory (needed by /log_json/erts-13.0/bin/beam.smp)
Error loading shared library libgcc_s.so.1: No such file or directory (needed by /log_json/erts-13.0/bin/beam.smp)
Error relocating /log_json/erts-13.0/bin/beam.smp: _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE10_M_replaceEmmPKcm: symbol not found
...

it seems like you need this now:

RUN apk add --no-cache openssl ncurses-libs libstdc++

(using erlang:25-alpine)

Container will not start

sys log shows the following;

Jun 4 09:35:05 sulaco 3006f477dede[2167]: Error loading shared library libstdc++.so.6: No such file or directory (needed by /dockerwatch/erts-12.0.2/bin/beam.smp) Jun 4 09:35:05 sulaco 3006f477dede[2167]: Error loading shared library libgcc_s.so.1: No such file or directory (needed by /dockerwatch/erts-12.0.2/bin/beam.smp)

Raising PR to fix docker image.

docker alpine cowboy

Hello,

Thank you for your great work. Working for some time with Yaws, I was curious about Cowboy. I managed to build a container based on your Dockerfile and create certs.

docker@boot2docker:/c/kklepper/test/cowboy$ docker run --rm -v /tmp:/tmp -v /www:/www -p 8012:8080 --name cb  kklepper/cowboy:alpine
No cookie is set or found. This limits the scripts functionality, installing, upgrading, rpc and getting a list of versions will not work.
Exec: /dockerwatch/erts-10.6.4/bin/erlexec -noshell -noinput +Bd -boot /dockerwatch/releases/1.0.0/dockerwatch -mode embedded -boot_var ERTS_LIB_DIR /dockerwatch/lib -config /dockerwatch/releases/1.0.0/sys.config -args_file /dockerwatch/releases/1.0.0/vm.args -- foreground
Root: /dockerwatch
/dockerwatch

I do not know what dockerwatch is or does, but the following worked for me:

docker@boot2docker:/mnt/sde1/tmp$ curl localhost:8012
<html>
    <head>
    <meta charset="utf-8">
    <title>dockerwatch</title>
    </head><ul>
</ul>
</body>

This looked promising.

I hoped to be able to point the root to www, but I didn't know how. I tried to find the file which was invoked with that empty and incomplete unordered list, but grep -ril "<title>dockerwatch</title>" just kept working with no output for hours.

Next I tried to redefine Dockerfile:

# test
WORKDIR www
#CMD ["/dockerwatch/bin/dockerwatch", "foreground"]
tail -f /tmp/cookie.txt

but this trick didn't work either. Where does Cowboy come into play?

To make a long story short: I have no idea what I'm doing here. Could you please help me?

I just want to use Cowboy like Caddy or Apache or NGINX or Yaws. How am I going to do that?

I don't know anything about Elixir and I sure don't want to use a monster container like the one from 99s (ontouchstart/cowboy 1.47GB, https://github.com/ninenines/cowboy).

After many hours of research for something which should be very easy to find (docker alpine cowboy) I run out of ideas.

Thank you very much.

Hello World

A idéia dessa primeiro escopo é criar um command line que envia uma msg Hello World via Telegram com as seguintes características:

  • Deploy com 3 instancias da aplicação em Regiões diferentes.
  • Criar um script de CHAOS monkey para testar
  • Ser possível fazer hot reload.

Use SSH to debug images

Add instructions on how to include and configure the ssh application in an image for easy debugging.

The "docker build -t erlang-dockerwatch ." command fails

Steps to reproduce :

  1. Clone the repository
  2. $ cd docker-erlang-example
  3. $ docker build -t erlang-dockerwatch .

Output:
...
Step 5/12 : WORKDIR dockerwatch
---> Running in 5b626d1d71c2
Removing intermediate container 5b626d1d71c2
---> e9c0d03312fa
Step 6/12 : RUN rebar3 as prod release
---> Running in 1f17811ab52f
===> Verifying dependencies...
===> Fetching cowboy v2.5.0
===> Fetching jsone v1.4.7
===> Fetching cowlib v2.6.0
===> Fetching ranch v1.6.2
===> Analyzing applications...
===> Compiling jsone
===> Compiling cowlib
===> Compiling ranch
===> Compiling cowboy
===> Analyzing applications...
===> Compiling dockerwatch
===> Assembling release "dockerwatch"-1.0.0...
===> Uncaught error in rebar_core. Run with DIAGNOSTIC=1 to see stacktrace or consult rebar3.crashdump
===> When submitting a bug report, please include the output of rebar3 report "your command"
The command '/bin/sh -c rebar3 as prod release' returned a non-zero code: 1

container fails to start

I get errors like these in syslog, possibly related to the issue reported at erlang/docker-erlang-otp#235

Jun 26 00:39:20 savile d98dae739d24[32358]: No cookie is set or found. This limits the scripts functionality, installing, upgrading, rpc and ge
tting a list of versions will not work.
Jun 26 00:39:20 savile d98dae739d24[32358]: dlsym: Resource temporarily unavailable
Jun 26 00:39:20 savile d98dae739d24[32358]: Aborted (core dumped)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.