Creating a Docker image from your code

One of the great developments that Heroku has open sourced are Buildpacks. Buildpacks are a collection of scripts that detect your application language/framework and install the required interpreters, libraries, etc. to run.

Buildstep is a great tool developed by progrium which uses these buildpacks to transform any application code (supported by any of the included buildpacks) into a self-sufficient Docker image. It is also used in the extremely popular Dokku project made by the same author.

In order to take full advantage of this amazing tool, we have created a base image called tutum/buildstep which can be used directly in a Dockerfile to produce application images with minimum effort.

Let’s see a simple example.

Converting a Django app into a Docker image using buildstep

Imagine we have a Django app and we want to convert it into a Docker image to be able to move it between hosts. In the application code folder, we’ll create the following Dockerfile:

FROM tutum/buildstep
EXPOSE 8000
CMD ["python", "manage.py", "runserver", "8000"]

That’s it. The minimum required information for tutum/buildstep to work is the port to expose and the command used to launch your application. Adding the application code and setting the working directory is automatically done by tutum/buildstep using the ONBUILD directive.

Let’s build it:

$ docker build -t fermayo/myapp .
Uploading context 99.84 kB
Uploading context
Step 0 : FROM tutum/buildstep
# Executing 3 build triggers
Step onbuild-0 : RUN mkdir -p /app
 ---> Running in 0d65c9537e8f
 ---> 9d7c609c38ce
Step onbuild-1 : ADD . /app
 ---> 3b7ff5e4f126
Step onbuild-2 : RUN /build/builder
 ---> Running in 6e7a796d93c3
       Python app detected
-----> No runtime.txt provided; assuming python-2.7.6.
-----> Preparing Python runtime (python-2.7.6)
-----> Installing Setuptools (2.1)
-----> Installing Pip (1.5.4)
-----> Installing dependencies using Pip (1.5.4)
       Downloading/unpacking Django==1.6.2 (from -r requirements.txt (line 1))
       Installing collected packages: Django
       Successfully installed Django
       Cleaning up...

-----> Discovering process types
       Procfile declares types -> web
 ---> 8758f592da19
 ---> 8758f592da19
Step 1 : EXPOSE 8000
 ---> Running in 3f10763973a8
 ---> db32c55e948b
Step 2 : CMD ["python", "manage.py", "runserver", "8000"]
 ---> Running in 7d122de7f8d3
 ---> ed1a72bfa5d0
Successfully built ed1a72bfa5d0
Removing intermediate container 0d65c9537e8f
Removing intermediate container d79aa6530641
Removing intermediate container 6e7a796d93c3
Removing intermediate container 3f10763973a8
Removing intermediate container 7d122de7f8d3

Our application is now Dockerized into an image called fermayo/myapp. Let’s try it out:

$ docker run -d -p 8000 fermayo/myapp

We have now our Django app up and running!

Converting a Heroku app into a Docker image using buildstep

Buildstep also supports using a Procfile to define the application process types. The following would be a simple Procfile for our Django app we used earlier:

web: python manage.py runserver 8000

To use this instead of manually defining the command, we can create the following Dockerfile:

FROM tutum/buildstep
EXPOSE 8000
CMD ["/start", "web"]

By entering the desired process type name in the CMD directive we are defining which command should be used to start the application.

Running your app without building an image using buildstep

If your application is stored in a git repository, you can also run tutum/buildstep passing in an environment variable GIT_REPO with its address and the container will clone the repo and install the dependencies, etc. on the fly:

# Without a Procfile
$ docker run -d -p 8000 -e GIT_REPO=https://github.com/fermayo/hello-world-django.git tutum/buildstep python manage.py runserver 8000
# With a Procfile (or relying on the default Procfile provided by the buildpack)
$ docker run -d -p 8000 -e GIT_REPO=https://github.com/fermayo/hello-world-php.git -e PORT=8000 tutum/buildstep /start web

So there is no need to build anything.

Give it a try!

This is a great way to getting started with Docker. Let us know if it works for your language/framework and how would you make it better.
Thanks for reading!

Update (01/22/2015)

Due to a change in the upstream image, applications are now run without root privileges, so port numbers lower than 1024 are unavailable for binding. The image tutum/buildstep and this blog post have been updated appropriately.

CTO & Co-founder of Tutum

Tagged with: , , , ,
Posted in Tutorial
12 comments on “Creating a Docker image from your code
  1. coopermaa says:

    Using a Procfile seems not work with node.js app:

    # With a Procfile
    $ cid=$(docker run -d -p 3000 -e GIT_REPO=https://github.com/coopermaa/nodejs-express-hello tutum/buildstep /start web)

    The container exits intermediately.

    $ docker logs $cid

    —–> Caching node_modules directory for future builds
    —–> Cleaning up node-gyp and npm artifacts
    —–> Building runtime environment
    —–> Discovering process types
    Procfile declares types -> web
    setuidgid: fatal: unable to setgid: permission denied

    My Procfile:
    web: node server.js

    Any idea?

  2. Borja Burgos says:

    We recently re-built this image, and that is causing these errors. We’re hoping to have a fix
    soon, sorry for the trouble!

  3. Kristopher says:

    Cada vez que empleo un amarre en ocasiones funciona de manera adecuada.
    ¿Tienen algún tipo de consecuencia?

  4. Kirk says:

    When building a java container with build step (especially framework buildpacks, like grails), there’s a huge pile of dependencies that have to be pulled every time you build the container. Is there a way to cache all this on the local machine using a volume or some other way so that all the downloading only needs to happen the first time?

  5. […] Creating a Docker image from your code […]

Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories
%d bloggers like this: