Fig simplified our complicated docker setup and life is awesome again.

Update: Fig has been replaced by Docker Compose, and is now deprecated. Docker Compose should serve as a drop-in replacement for used in this article.

What is fig?

Fig is a python application that helps you run groups of docker containers. The docker command line interface is awesome, but if you start working with many containers at once and link them in the development environment, typing the commands into the command line gets burdensome.

The most pragmatic approach to this problem is creating a bash script:  
# Usage:
# `./`
# or
# `./ python test`
# Postgres container
docker run -d -v /var/docker/postgresql:/data --name=postgres -e USER='root' \  
    -e PASS='amazing_pass' -e DB='my_db' paintedfox/postgresql
# Redis container
docker run -d -v /var/docker/redis:/data -p \  
    --name=redis dockerfile/redis
# Rabbit container
docker run -d -v /var/docker/rabbit:/data -p \  
    -p -e RABBITMQ_PASS="amazing_pass" \
    --name=rabbitmq tutum/rabbitmq
# Worker container
docker run -i -t -e INSTANCE_TYPE="worker" --name='my-worker' \  
    -v /home/syncano/app:/home/syncano/app \
    --link=postgres:postgres --link=redis:redis --link=rabbitmq:rabbit my_docker_image &
# Web server container
docker run -i -t -e INSTANCE_TYPE="web-server" --name='my-web' -p \  
    -v /home/my/app:/home/my/app
    --link=postgres:postgres --link=redis:redis --link=rabbitmq:rabbit my_docker_image "$@"

Woah, it's super complicated and ugly – and that's only for running containers. What about inspecting containers, stopping them, or rebuilding them? You need more scripts for that. Managing docker this way can easily become a nightmare. Luckily, you can use instead.

Fig lets you configure the setup of your docker containers with a simple yaml file and provides you with commands such as:

  • up - runs all containers; builds containers if none are available
  • rm - removes containers
  • ps - inspects the state of all containers in your app and gives you easy access to logs from all your containers at once:

Fig logs

How do you get started with fig?

Step 1 - Install it.

Fig is available in pip, so all you have to do is type this into your command line:

$ sudo pip install fig

You can more information about installing on the official website.

Step 2 - Create a fig config.

Fig config is written in yaml and is called fig.yml - you should place it in the directory in which you want to call fig commands.

Fig helps you manage docker containers, so its options are similar to those of the docker run command. In fig.yml, you'll start by entering the name of the container. Then, choose build or image to either run docker build or start a container based on the image you specified, respectively. You can specify many containers this way. Here's a simple example:

  build: . # will run docker build in local directory
  image: redis

Of course you can do more things, like forwarding ports by choosing the ports field , mounting directories using the volumes field, and linking containers with links. It's really intuitive! You can read more about configuration options in the fig.yml reference.

Now for a less-simple example. Here's how you can migrate your first nightmarish bash script to fig.yml.

    image: paintedfox/postgresql
        - USER=root
        - PASS=awesome_pass
        - DB=my_db
        - "5432"
        - /var/docker/postgresql:data
    image: dockerfile/redis
        - /var/docker/redis:data
        - "6379"
    image: tutum/rabbitmq
        - /var/docker/rabbit:data
        - RABBITMQ_PASS=awesome_pass
        - "5672"
        - "15672"
    build: .
        - "8000:8000"
        - postgres:postgres
        - redis:redis
        - rabbit:rabbit
        - .:/home/my/app
        - INSTANCE_TYPE=web-server
    build: .
        - postgres:postgres
        - redis:redis
        - rabbit:rabbit
        - .:/home/my/app
        - INSTANCE_TYPE=worker

To run containers, now use:

$ fig up

In another terminal window, you can inspect all of your containers with:

$ fig ps
Name                         Command               State                 Ports  
app_redis_1      redis-server /etc/redis/re ...   Up      49417->6379/tcp  
app_postgres_1   /sbin/my_init                    Up      49418->5432/tcp  
app_rabbit_1     /                          Up      49419->15672/tcp, 49420->5672/tcp  
app_worker_1     /sbin/my_init                    Up      8000/tcp, 2023->22/tcp  
app_web_1        /sbin/my_init                    Up      8000->8000/tcp, 2022->22/tcp  

That's it! Pretty easy, right?

Issues with fig (troubleshooting)

Unexpected quotes in environment variables

I'm used to wrapping string environment variables in double quotes " ". I did the same in my fig.yml config and to my surprise app wasn't working.

This is how I configured my INSTANCETYPE_ variable:

    - INSTANCE_TYPE="web-server"

During debugging I noticed that fig leaves double quotes in actual variable value:

$ fig run web printenv

So, my advice is to strip quotes in environment specification.

Rebuilding images

I also noticed fig occasionally doesn't notice when a Dockerfile changes and its image needs to be rebuilt. When that happens, you'll just need to enter this into the command line:

$ fig rm  # removes containers
$ fig build  # rebuild images
$ fig up  # run whole setup again


Fig simplified our complicated docker setup.
If you're looking for improving your docker workflow even more, check out nsenter - a tool for entering docker containers - and serf - a decentralized solution for cluster membership, failure detection, and orchestration.