Fig ==== Punctual, lightweight development environments using Docker. Fig is a tool for defining and running isolated application environments. You define the services which comprise your app in a simple, version-controllable YAML configuration file that looks like this: ```yaml web: build: . links: - db ports: - 8000:8000 db: image: orchardup/postgresql ``` Then type `fig up`, and Fig will start and run your entire app: $ fig up Pulling image orchardup/postgresql... Building web... Starting example_db_1... Starting example_web_1... example_db_1 | 2014-01-02 14:47:18 UTC LOG: database system is ready to accept connections example_web_1 | * Running on http://0.0.0.0:5000/ There are commands to: - start, stop and rebuild services - view the status of running services - tail running services' log output - run a one-off command on a service Fig is a project from [Orchard](https://orchardup.com), a Docker hosting service. [Follow us on Twitter](https://twitter.com/orchardup) to keep up to date with Fig and other Docker news. Getting started --------------- Let's get a basic Python web app running on Fig. It assumes a little knowledge of Python, but the concepts should be clear if you're not familiar with it. First, install Docker. If you're on OS X, you can use [docker-osx](https://github.com/noplay/docker-osx): $ curl https://raw.github.com/noplay/docker-osx/master/docker > /usr/local/bin/docker $ chmod +x /usr/local/bin/docker $ docker version Docker has guides for [Ubuntu](http://docs.docker.io/en/latest/installation/ubuntulinux/) and [other platforms](http://docs.docker.io/en/latest/installation/) in their documentation. Next, install Fig: $ sudo pip install fig You'll want to make a directory for the project: $ mkdir figtest $ cd figtest Inside this directory, create `app.py`, a simple web app that uses the Flask framework and increments a value in Redis: ```python from flask import Flask from redis import Redis import os app = Flask(__name__) redis = Redis( host=os.environ.get('FIGTEST_REDIS_1_PORT_6379_TCP_ADDR'), port=int(os.environ.get('FIGTEST_REDIS_1_PORT_6379_TCP_PORT')) ) @app.route('/') def hello(): redis.incr('hits') return 'Hello World! I have been seen %s times.' % redis.get('hits') if __name__ == "__main__": app.run(host="0.0.0.0", debug=True) ``` We define our Python dependencies in a file called `requirements.txt`: flask redis And we define how to build this into a Docker image using a file called `Dockerfile`: FROM stackbrew/ubuntu:13.10 RUN apt-get -qq update RUN apt-get install -y python python-pip ADD . /code WORKDIR /code RUN pip install -r requirements.txt EXPOSE 5000 CMD python app.py That tells Docker to create an image with Python and Flask installed on it, run the command `python app.py`, and open port 5000 (the port that Flask listens on). We then define a set of services using `fig.yml`: web: build: . ports: - 5000:5000 volumes: - .:/code links: - redis redis: image: orchardup/redis This defines two services: - `web`, which is built from `Dockerfile` in the current directory. It also says to forward the exposed port 5000 on the container to port 5000 on the host machine, connect up the `redis` service, and mount the current directory inside the container so we can work on code without having to rebuild the image. - `redis`, which uses the public image [orchardup/redis](https://index.docker.io/u/orchardup/redis/). Now if we run `fig up`, it'll pull a Redis image, build an image for our own app, and start everything up: $ fig up Pulling image orchardup/redis... Building web... Starting figtest_redis_1... Starting figtest_web_1... figtest_redis_1 | [8] 02 Jan 18:43:35.576 # Server started, Redis version 2.8.3 figtest_web_1 | * Running on http://0.0.0.0:5000/ Open up [http://localhost:5000](http://localhost:5000) in your browser (or [http://localdocker:5000](http://localdocker:5000) if you're using [docker-osx](https://github.com/noplay/docker-osx)). That's it! You can also pass the `-d` flag to `fig up` to run your services in the background, and use `fig ps` to see what is currently running: $ fig up -d Starting figtest_redis_1... Starting figtest_web_1... $ fig ps Name Command State Ports ------------------------------------------------------------------- figtest_redis_1 /usr/local/bin/run Up figtest_web_1 /bin/sh -c python app.py Up 5000->5000/tcp `fig run` allows you to run one-off commands for your services. For example, to see what environment variables are available to the `web` service: $ fig run web env Run `fig --help` to see what other commands are available. You'll probably want to stop them when you've finished: $ fig stop That's more-or-less how Fig works. See the reference section below for full details on the commands, configuration file and environment variables. Reference --------- ### fig.yml Each service defined in `fig.yml` must specify exactly one of `image` or `build`. Other keys are optional, and are analogous to their `docker run` command-line counterparts. As with `docker run`, options specified in the Dockerfile (e.g. `CMD`, `EXPOSE`, `VOLUME`, `ENV`) are respected by default - you don't need to specify them again in `fig.yml`. ```yaml -- Tag or partial image ID. Can be local or remote - Fig will attempt to pull if it doesn't exist locally. image: ubuntu image: orchardup/postgresql image: a4bc65fd -- Path to a directory containing a Dockerfile. Fig will build and tag it with a generated name, and use that image thereafter. build: /path/to/build/dir -- Override the default command. command: bundle exec thin -p 3000 -- Link to containers in another service (see "Communicating between containers"). links: - db - redis -- Expose ports. Either specify both ports (HOST:CONTAINER), or just the container port (a random host port will be chosen). ports: - 3000 - 8000:8000 -- Map volumes from the host machine (HOST:CONTAINER). volumes: - cache/:/tmp/cache -- Add environment variables. environment: RACK_ENV: development ``` ### Environment variables Fig uses [Docker links] to expose services' containers to one another. Each linked container injects a set of environment variables, each of which begins with the uppercase name of the container. name\_PORT
Full URL, e.g. `MYAPP_DB_1_PORT=tcp://172.17.0.5:5432` name\_PORT\_num\_protocol
Full URL, e.g. `MYAPP_DB_1_PORT_5432_TCP=tcp://172.17.0.5:5432` name\_PORT\_num\_protocol\_ADDR
Container's IP address, e.g. `MYAPP_DB_1_PORT_5432_TCP_ADDR=172.17.0.5` name\_PORT\_num\_protocol\_PORT
Exposed port number, e.g. `MYAPP_DB_1_PORT_5432_TCP_PORT=5432` name\_PORT\_num\_protocol\_PROTO
Protocol (tcp or udp), e.g. `MYAPP_DB_1_PORT_5432_TCP_PROTO=tcp` name\_NAME
Fully qualified container name, e.g. `MYAPP_DB_1_NAME=/myapp_web_1/myapp_db_1` [Docker links]: http://docs.docker.io/en/latest/use/port_redirection/#linking-a-container