Dart meets Docker (how to dockerize dart apps)

05 Mar 2014

Docker is an open-source engine that automates the deployment of applications as portable and self-sufficient containers that will run virtually anywhere. Dockerized applications reduce configuration efforts and obstacles for administrators. Applications can be provided in a configured, self-sufficient and frictionless way.

Dart is a web programming language mainly developed by Google with the intention to provide an alternative to JavaScript (the actual de facto standard in web client side programming). Nevertheless Dart can be used to develop server side programs (see Tour de Dart Part II for more details concerning server side programming with Dart).

Dart and Docker are a great fit to provide frictionless deployable Dart apps. All you have to do is to supply an additional Dockerfile to an existing Dart package. This post show how to do this.

Containerdart is a very simple Dart HTTP server using the Sinatra inspired web framework Start to provide static content.

import 'package:start/start.dart';

main() {
  start(host: '0.0.0.0', port: 8080).then((Server app) {
    app.static('../build/web');
  });
}

Containerdart is provided via github as a general blueprint how Dart applications can be seamlessly dockerized.

In the next steps you will learn

  • how to install dockerized Dart applications from Github by installing Containerdart as a simple example
  • and how Containerdart has been dockerized using an additonal Dockerfile.

Install Containerdart using Docker

All you need is a system where docker is installed on. You can install docker following the install instructions provided by Docker.

Dockerized applications hosted on Github can be installed by docker with one command. We take Containerdart as an example.

docker build -t containerdart github.com/nkratzke/containerdart

Docker downloads specified repository from github and processes a Dockerfile in it to create an image from it. If image creation is completed you can instantiate a container from this image with the following command.

docker run -p 8888:8080 -d containerdart

Last command starts the container as a daemon and binds the container internal port 8080 to the host port 8888 (it is also possible to map the exposed container port 8080 to any other port number, e.g. 80). The container provided webserver should be accessible on http://localhost:8888.

You can run

docker ps

to see that a container containing our simple Dart based HTTP server is running.

If it is working you should see this webpage.

How is it working

It is recommended to inspect the git repository of Containerdart on github. You will see it is a normal Dart package except one additional file called Dockerfile. Docker uses dockerfiles to automate image generation. It is a great and simple format to define deployments.

# Install a dart container for demonstration purposes.
# Your dart server app will be accessible via HTTP on container port 8080.
# You should adapt this Dockerfile to your needs.
# If you are new to Dockerfiles please read
# http://docs.docker.io/en/latest/reference/builder/
# to learn more about Dockerfiles.

FROM stackbrew/ubuntu:13.10
MAINTAINER Nane Kratzke <nane@nkode.io>

# Install Dart SDK. Do not touch this until you know what you are doing.
# We do not install darteditor nor dartium because this is a server container.
# See: http://askubuntu.com/questions/377233/how-to-install-google-dart-in-ubuntu
RUN apt-get update
RUN apt-get install -y software-properties-common python-software-properties
RUN apt-add-repository ppa:hachre/dart
RUN apt-get -y update
RUN apt-get install -y dartsdk

# Install the dart server app. Add additional directories if necessary for your app.
ADD pubspec.yaml /container/pubspec.yaml
ADD bin          /container/bin
ADD web          /container/web

# Build the app. Do not touch this.
WORKDIR /container
RUN pub build

# Expose port 8080. You should change it to the port(s) your app is serving on.
EXPOSE 8080

# Entrypoint.
# Whenever the container is started the following command is executed in your container.
# In most cases it simply starts your app.
WORKDIR /container/bin
ENTRYPOINT ["dart"]

# Change this to your starting dart.
CMD ["httpserver.dart"]

This file explains docker what to do when

docker build -t containerdart github.com/nkratzke/containerdart

is called. So the above shown Dockerfile extends

  • a barebone Ubuntu 13.10 system,
  • installs additionally Dart SDK,
  • copies the application files into the container (bin and web directory),
  • starts the build process on the system,
  • defines an entrypoint (which is being called when the container is started by docker).

It can be easily adapted to other Dart apps. Just clone the Containerdart repository and adapt it to your needs.

A slightly more complex example (Dartchat)

Dartchat is another server side Dart app providing a simple websocket based chat server. It is available via github or pub.dartlang.org. Dartchat is an example of second part of the Tour de Dart.

You can install it using docker

docker build -t dartchat github.com/nkratzke/dartchat

and run it like this

docker run -p 8080:3000 -d dartchat

Accessing http://localhost:8080 will provide you following webpage:

The responsible Dockerfile of Dartchat looks like this:

# Install a dartchat as a docker container.
# Dartchat will be exposed via HTTP on port 3000.
#
# This file is hosted on github. Therefore you can start it in docker like this:
# > docker build -t dartchat github.com/nkratzke/dartchat
# > docker run -p 8080:3000 -d dartchat

FROM stackbrew/ubuntu:13.10
MAINTAINER Nane Kratzke <nane@nkode.io>

# Install Dart SDK. Do not touch this until you know what you are doing.
# We do not install darteditor nor dartium because this is a server container.
# See: http://askubuntu.com/questions/377233/how-to-install-google-dart-in-ubuntu
RUN apt-get update
RUN apt-get install -y software-properties-common python-software-properties
RUN apt-add-repository ppa:hachre/dart
RUN apt-get -y update
RUN apt-get install -y dartsdk

# Install the dart server app.
ADD pubspec.yaml /container/pubspec.yaml
ADD lib          /container/lib
ADD bin          /container/bin
ADD web          /container/web

# Build the app. Do not touch this.
WORKDIR /container
RUN pub build

# Expose port 3000.
EXPOSE 3000

# Entrypoint.
WORKDIR /container/bin
ENTRYPOINT ["dart"]

# Change this to your starting dart.
CMD ["chartserver.dart"]

Closing remarks regarding docker (on non linux systems)

If docker is used on a non linux system like Mac OS X it is likely that docker uses VirtualBox under the hood. In theses cases you must configure port forwarding in virtual box. So if you are exposing port 8080 in your docker container mapping it to port 8888 for the outside world you must forward host port 8888 to docker-vm port 8888 in virtualbox. How to do this is explained here.


comments powered by Disqus
© Nane Kratzke (All rights reserved)
Twitter Slideshare Github Researchgate LinkedIN Xing Google Plus RSS