Desenvolvendo com Docker Compose

Neste post vou falar um pouco sobre Docker Compose e como usá-lo em desenvolvimento, estou usando Docker version 1.10.2 e docker-compose version 1.6.2.

Que diabos é Docker Compose?

O Docker Compose é uma ferramenta para definição e execução de aplicações Docker multi-container. Isso significa que com ele você pode definir várias aplicações como container e executá-las de uma única vez sem precisar executar várias vezes docker build -t [myuser]/[appname] . && docker run [myuser]/[appname]. Isso é uma mão na roda gigante :).

Como o Docker Compose pode me ajudar?

Com o compose acabou aquela situação em que você tem um amigo designer ou front-end e ele tenta rodar a app que ta no repositório, não consegue e você precisa configurar a máquina dele para o trabalho, sem falar no tempo perdido configurando VMs e na diminuição do consumo de ram da sua máquina... Usando o compose em apenas um arquivo você define as dependências do seu ambiente: banco de dados, bancos nosql, variáveis de ambiente, serviços e etc e em seguida com apenas um comando você sobe todo essa pilha e já pode usar. Sua equipe de front-end agora apenas da um git clone [repo] && docker-compose run --service-ports web e já pode trabalhar.

Hands ON

Vamos imaginar uma app simples, um hello world por exemplo :D, farei este teste usando PHP e Ruby, Primeiro de tudo temos que criar um Dockerfile, nele iremos definir a imagem que iremos usar e os comandos necessários para importar nossa app em um container.

PHP - Dockerfile

        
        FROM php
        RUN mkdir /app
        WORKDIR /app
        RUN wget https://getcomposer.org/composer.phar
        ADD composer.json /app/composer.json
        ADD composer.lock /app/composer.lock
        RUN ./composer.phar install
        ADD . /app/
        
      

RUBY - Dockerfile

        
        FROM ruby
        RUN mkdir /app
        WORKDIR /app
        ADD Gemfile /app/Gemfile
        ADD Gemfile.lock /app/Gemfile.lock
        RUN bundle install
        ADD . /app/
        
      

Em seguida vamos criar um arquivo chamado docker-compose.yml e definir os serviços nele. Serviços são uma espécie de alias para o containers que vão ser criados ex: web - para aplicações web, db - para banco de dados. Você pode definir quantos serviços quiser, desde que possuam nomes diferentes, pois quando os containers forem levantados esses "apelidos" poderão ser usandos na comunicação entre eles.

Obs: para saber mais sobre a questão de versão do docker-compose acesse https://docs.docker.com/compose/compose-file/#versioning

PHP - docker-compose.yml

        
        version: '2'
        services:
          web:
            build: .
            command: php -S 0.0.0.0:8000 -t /app/web/ # comando a ser executado quando o conatiner web terminar o build
            ports:
              - "8000:8000" # porta que será mapeada com o host
            volumes:
              - .:/app # volume que será mapeado "." - root da aplicação, "/app" - diretório no container
        
      

Ruby - docker-compose.yml

        
        version: '2'
        services:
          web:
            build: .
            command: bundle exec ruby hello.rb
            ports:
              - "3000:3000"
            volumes:
              - .:/app
            environment:
              PORT: 3000
        
      

Depois de definido o Dockerfile e o docker-compose.yml vamos agora fazer nossos apps helloworld.

Para PHP irei usar o Silex e para ruby o Sinatra.

PHP - Estrutura do diretório

        
        .
        ├── composer.json
        ├── composer.lock
        ├── docker-compose.yml
        ├── Dockerfile
        ├── scripts
        │   └── run
        └── web
            └── index.php
        
      

PHP - composer.json

        
        {
            "require": {
                "silex/silex": "^1.3"
            }
        }
        
      

PHP - web/index.php

        
            <?php
            require_once __DIR__.'/../vendor/autoload.php';

            $app = new Silex\Application();

            $app->get('/', function() use($app) {
              return "You are in home";
            });

            $app->get('/{name}', function($name) use($app) {
                return 'Hello '.$app->escape($name);
            });

            $app->run();
            ?>
          
      

Ruby - estrutura do diretório

        
         .
        ├── docker-compose.yml
        ├── Dockerfile
        ├── Gemfile
        ├── Gemfile.lock
        ├── hello.rb
        └── scripts
            └── run
        
      

Ruby - Gemfile

        
        source 'https://rubygems.org'

        gem 'sinatra'
        gem 'sinatra-contrib'
        
      

Ruby - hello.app

        
          require 'sinatra'
          require "sinatra/reloader" if development?

          set :bind, '0.0.0.0'
          set :port, ENV['PORT']

          get '/' do
            "You are in home"
          end
          get '/:name' do
            "Hello #{params['name']}!"
          end
        
      

Executando os containers

Para executar os containers vamos rodar o seguinte o comando no root da aplicação docker-compose up. Esse comando fara com que os containers sejam levantados e os comandos definidos no docker-compose.yml e no DOckerfile sejam executados.

Como vocês devem ter percebido na estrutura de diretórios tem uma pasta chamada scripts, com um script chamado run. Eu faço isso para facilitar minha vida, nesse script tem apenas uma linha com o comando citado acima, então quando quero rodar os containers apenas faço ./scripts/run.

Após rodar o comando é só acessar localhost:8000 para a aplicação PHP e localhost:3000 para a aplicação Ruby, qualquer alteração feita na aplicação será replicada no container por conta do mapeamento de volumes que fizemos no docker-compose.yml volumes: - .:/app

Executando comandos dentro do container

Caso precisem executar comandos dentro do container vocês pode fazer da seguinte maneira: docker-compose run web [comando] ex:
        
          $ docker-compose run web ruby -v
          ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]

          $ docker-compose run web php -v
          PHP 7.0.4 (cli) (built: Mar 19 2016 00:06:16) ( NTS )
          Copyright (c) 1997-2016 The PHP Group
          Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
        
      

Instalando novas depedências no projeto

Sempre que uma nova dependência for adicionada ao projeto é necessário executar docker-compose build para que uma nova imagem seja criada com as dependências instaladas.

É isso aí pessoal, divirtam-se!!! O reposótio com os exemplos está aqui: https://github.com/gwmoura/hello-docker-compose;)

anúncio