Using Docker Compose

June 05, 2018


"Compose is a tool for defining and running multi-container applications with Docker. 
With Compose, you define a multi-container application in a single file, then spin your application up in a single command which does everything that needs to be done to get it running." (from Overview of Docker Compose)
Simple three steps to use Docker Compose.
  1. Define your app’s environment with a Dockerfile so it can be reproduced anywhere.
  2. Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.
  3. Lastly, run docker-compose up and Compose will start and run your entire app.
In this Chapter, we are going to learn how to use Docker Compose with the simple application shown below.
docker-ppt-compose-001.png

5-1. Let's create simple Docker Compose

  1. Make a directory with the name "compose" under ~workspace/docker
    $ mkdir -p ~/workspace/docker/compose
    $ cd ~/workspace/docker/compose
  2. Create an application
    $ vi app.py
    from flask import Flask
    from redis import Redis
    import os
    app = Flask(__name__)
    redis = Redis(host='redis', port=6379)
    
    @app.route('/')
    def hello():
        redis.incr('counter')
        return'Hi! You saw me %s times.'% redis.get('counter')
    
    if __name__ == "__main__":
        app.run(host="0.0.0.0", debug=True)
    
    This application increments the counter in redis each time you access it with web browser.
  3. Create requirements file
    $ vi requirements.txt
    flask
    redis
    
  4. Create Dockerfile
    $ vi Dockerfile
    FROM python:2.7
    ADD . /code
    WORKDIR /code
    RUN pip install -r requirements.txt
    
  5. Create docker-compose.yml
    $ vi docker-compose.yml
    web:
        build: .
        command: python app.py
        ports:
            - "5000:5000"
        volumes:
            - .:/code
        links:
            - redis
    redis:
        image: redis
    
    In this example, we define the Multi-Container application which has "web" and "redis" containers in compose.
    docker-ppt-compose-002.png
  6. Start the Multi-Container Application
    $ docker-compose up -d
    [AKIRA@^_^:compose]$ docker-compose up -d
    Pulling redis (redis:latest)...
    latest: Pulling from library/redis
    ba249489d0b6: Pull complete
    :
    Status: Downloaded newer image for redis:latest
    Creating compose_redis_1...
    :
    Building web...
    Step 0 : FROM python:2.7
    2.7: Pulling from library/python
    843e2bded498: Pull complete
    8c00acfb0175: Pull complete
    :
    Successfully built 1622bc6ab5bb
    Creating compose_web_1...
    
  7. Check the running containers
    $ docker-compose ps
    [AKIRA@^_^:compose]$ docker-compose ps
     Name            Command                     State  Ports
    compose_redis_1 /entrypoint.sh redis-server  Up    6379/tcp
    compose_web_1   python app.py                Up    0.0.0.0:5000->5000/tcp
    
    We can see that 2 containers are started by Docker Compose.
    The port 5000 of compose_web_1 container is bound to the port 5000 of Docker Host (vm-appcat01).
  8. Check the IP Address of vm-appcat01
    [AKIRA@^_^:dockerfiles]$ docker-machine ls
    NAME        ACTIVE DRIVER            STATE   URL                       SWARM
    vm-appcat01 *      vmwareappcatalyst Running tcp://172.16.194.154:2376
    
  9. Access the application with the browser.
    172.16.194.154:5000
    
    docker-compose-browser-1.png
  10. Access again, and the counter gets incremented by 1.
    (The counter on redis got incremented)
  11. Edit your application
    $ vi app.py
    return'Hey Dude, You saw me %s times.'% redis.get('counter')
    
    From "Hi" to "Hey Dude"
  12. Access your application
    docker-compose-browser-3.png
    Your Web application is updated (Hi -> Hey Dude)
    redis counter gets incremented (counter = 3)
  13. Display logs
    $ docker-compose logs
    [AKIRA@^_^:compose]$ docker-compose logs
    Attaching to compose_web_1, compose_redis_1
    web_1   |  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
    :
    
  14. Stop the containers
    $ docker-compose stop
    [AKIRA@^_^:compose]$ docker-compose stop
    Stopping compose_web_1... done
    Stopping compose_redis_1... done
    
  15. Access your application with Web browser.
    (App is down)
  16. Restart your containers
    $ docker-compose up -d
    [AKIRA@^_^:compose]$ docker-compose up -d
    Starting compose_redis_1...
    Starting compose_web_1...
    
  17. Access your application
    docker-compose-browser-4.png
    redis counter is kept and incremented even after restart. (counter = 4)
  18. Stop the containers
    $ docker-compose stop
  19. Remove the containers
    $ docker-compose rm
    Both web and redis containers are removed.

5-2. Scaling out your app

Let's scale out your web application with docker-compose.
  1. Edit docker-compose.yml
    $ vi docker-compose.yml
    web:
        build: .
        command: python app.py
        ports:
            - "5000"
        volumes:
            - .:/code
        links:
            - redis
    redis:
        image: redis
    
    In the first example, we bind port 5000 of docker host to port 5000 of web container. (- "5000:5000")
    This prevents us from scaling out the web container because the port 5000 on docker host would be in use by the first web container.
    So this time we set this as - "5000".
    This will bind the port 5000 of "web" container to arbitrary port of docker host.
  2. Start the containers with Docker Compose
    $ docker-compose up -d
    [AKIRA@^_^:compose]$ docker-compose up -d
    Creating compose_redis_1...
    Building web...
    
  3. Check the running containers
    $ docker-compose ps
    [AKIRA@^_^:compose]$ docker-compose ps
    Name            Command                      State   Ports
    compose_redis_1 /entrypoint.sh redis-server  Up      6379/tcp
    compose_web_1   python app.py                Up      0.0.0.0:32768->5000/tcp
    
    Note the port number of compose_web_1.
    Port 5000 of container is bound to 32768 of the Docker Host (vm-appcat01).
  4. Check the IP Address of Docker Host (vm-appcat01)
    $ docker-machine ip vm-appcat01
    [AKIRA@^_^:compose]$ docker-machine ip vm-appcat01
    172.16.194.161
    
    You can use docker-machine ls, too.
  5. Now, we scale out the web container by 1 (make it 2)
    $ docker-compose scale web=2
    [AKIRA@^_^:compose]$ docker-compose scale web=2
    Creating and starting 2... done
    
  6. Check the running containers
    $ docker-compose ps
    [AKIRA@^_^:compose]$ docker-compose ps
    Name             Command                      State Ports
    compose_redis_1  /entrypoint.sh redis-server  Up    6379/tcp
    compose_web_1    python app.py                Up    0.0.0.0:32768->5000/tcp
    compose_web_2    python app.py                Up    0.0.0.0:32769->5000/tcp
    
    You can see there are two "web" containers running.
  7. Let's make it 10!
    $ docker-compose scale web=10
    [AKIRA@^_^:compose]$ docker-compose scale web=10
    Creating and starting 3... done
    Creating and starting 4... done
    Creating and starting 5... done
    Creating and starting 6... done
    Creating and starting 7... done
    Creating and starting 8... done
    Creating and starting 9... done
    Creating and starting 10... done
    
    Now you have 10 web containers running.
    docker-ppt-compose-003.png
  8. Check it out.
    $ docker-compose ps
    [AKIRA@^_^:compose]$ docker-compose ps
    Name                     Command             State     Ports
    compose_redis_1  /entrypoint.sh redis-server Up     6379/tcp
    compose_web_1    python app.py               Up     0.0.0.0:32769->5000/tcp
    compose_web_10   python app.py               Up     0.0.0.0:32770->5000/tcp
    compose_web_2    python app.py               Up     0.0.0.0:32768->5000/tcp
    compose_web_3    python app.py               Up     0.0.0.0:32774->5000/tcp
    compose_web_4    python app.py               Up     0.0.0.0:32773->5000/tcp
    compose_web_5    python app.py               Up     0.0.0.0:32777->5000/tcp
    compose_web_6    python app.py               Up     0.0.0.0:32771->5000/tcp
    compose_web_7    python app.py               Up     0.0.0.0:32772->5000/tcp
    compose_web_8    python app.py               Up     0.0.0.0:32775->5000/tcp
    compose_web_9    python app.py               Up     0.0.0.0:32776->5000/tcp
    
  9. Now we make "web" containers to 3 and redis to 2.
    $ docker-compose scale web=3 redis=2
    [AKIRA@^_^:compose]$ docker-compose scale web=3 redis=2
    Stopping compose_web_4... done
    Stopping compose_web_5... done
    Stopping compose_web_6... done
    Stopping compose_web_7... done
    Stopping compose_web_8... done
    Stopping compose_web_9... done
    Stopping compose_web_10... done
    Removing compose_web_10... done
    Removing compose_web_6... done
    Removing compose_web_5... done
    Removing compose_web_8... done
    Removing compose_web_7... done
    Removing compose_web_4... done
    Removing compose_web_9... done
    Creating and starting 2... done
    
  10. Check it.
    $ docker-compose ps
    [AKIRA@^_^:compose]$ docker-compose ps
     Name                 Command                State    Ports
    compose_redis_1  /entrypoint.sh redis-server Up    6379/tcp
    compose_redis_2  /entrypoint.sh redis-server Up    6379/tcp
    compose_web_1    python app.py               Up    0.0.0.0:32769->5000/tcp
    compose_web_2    python app.py               Up    0.0.0.0:32768->5000/tcp
    compose_web_3    python app.py               Up    0.0.0.0:32774->5000/tcp
    
    Now we know that we can scale-in and out ”web" and "redis" independently. That's really good.
  11. Stop the containers
    $ docker-compose stop
    [AKIRA@^_^:compose_]$ docker-compose stop
    Stopping compose_redis_2... done
    Stopping compose_web_3... done
    Stopping compose_web_2... done
    Stopping compose_web_1... done
    Stopping compose_redis_1... done
    
  12. Remove the containers
    $ docker-compose rm
    [AKIRA@^_^:compose]$ docker-compose rm
    Going to remove compose_redis_2, compose_web_3, compose_web_2, compose_web_1, compose_redis_1
    Are you sure? [yN] y
    Removing compose_redis_2... done
    Removing compose_web_3... done
    Removing compose_web_2... done
    Removing compose_web_1... done
    Removing compose_redis_1... done

No comments:

Powered by Blogger.