Alpine – Faça você mesmo

Oi Pessoal,

O MundoDocker trás hoje para você um pequeno tutorial de como é possível criar uma imagem enxuta, somente com o que você precisa e utilizando menos espaço possível. Para isso será necessário utilizar uma das duas imagens mais limpas do Docker, são elas: Alpine ou BusyBox, nesse tutorial vamos focar na Alpine, uma das mais buscadas atualmente.

Para que não conhece, a Alpine é uma distribuição construída com musl libc e BusyBox, que é conhecida como canivete suíço, pois combina versões minúsculas de muitos utilitários comuns no UNIX em um único pequeno executável. Algumas características de Alpine:

Pequena

Enquanto a menor imagem para Docker precisa de cerca de 130MB de espaço em disco, a Alpine precisa de no máximo 8MB, isso faz com que, mesmo você montando todo o seu ambiente, ele nunca terá o mesmo tamanho do que se montando em um imagem tradicional, isso é ótimo, pois deixa o ambiente ainda mais enxuto e simples de migrar.

Simples

Você tem apenas aquilo que é necessário para o funcionamento de sua aplicação, se precisar de mais alguma biblioteca, é só instalar, você não precisa se preocupar em desativar ou remover lixos, eles simplesmente não existem.

Segura

Alpine foi desenvolvida pensando em segurança, e para garantir isso os desenvolvedores se preocuparam aprimorar os recursos de segurança do kernel como grsecurity/PaX, além disso, todos os binários foram compilados em executáveis independente de posição, isso previne alguns uso problemas relacionados a buffer overflow e outros tipos de ataques envolvendo estouro de pilha.

Mãos a obra?

Nosso exemplo consistirá em montarmos uma imagem de com Alpine e Nodejs, e vamos comparar o tamanho da nova imagem que montamos com Alpine e outras distros disponíveis.

A Aplicação:

Será algo bem simples, apenas uma aplicação olá mundo:

var http = require('http');
http.createServer(function(req,res) {
 res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
 res.end('Exemplo Node.js Mundo Docker!');
}).listen(8080);

Colocamos o nome de app.js, não esqueça de criar o package.json com as dependências da aplicação:

{
"name": "docker_web_app",
"version": "1.0.0",
"description": "Node.js on Docker",
"author": "First Last <[email protected]>",
"main": "app.js"
}

Agora criamos nosso Dockerfile:

FROM alpine:3.1
# Update
RUN apk add --update nodejs
# Cria a pasta da app
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Instala as dependencias da app
COPY package.json /usr/src/app/
RUN npm install
# copia a app
COPY . /usr/src/app
EXPOSE 8080
CMD ["node", "/usr/src/app/app.js"]

 

Não é nada muito complexo, basta você informar qual imagem base utilizará, e a diferença está no instalador de dependências, que para o Alpine é o apk. Agora vamos gerar a imagem:

docker build -t alpineteste .

Será gerado uma nova imagem com o nome de alpineteste, agora vamos comparar o tamanho dessa imagem com outras:

Alpine

Lembrando, que utilizamos a imagem base de cada distribuição e em cima dela instalamos o node e subimos essa aplicação, note que a diferença é exorbitante, isso por que a Alpine tem apenas o que é necessário para essa aplicação rodar, nada além disso.

Como podem ver, utilizando essa abordagem seu ambiente fica ainda mais escalável, e claro ainda mais portável, pois quanto menos a sua imagem, melhor é para transitar ela entre os hosts (não é necessário baixar megas e megas da imagem no primeiro deploy por exemplo) .

Gostou? nos ajude divulgando o Blog 😉

Grande abraço!

Ansible

Olá pessoal,

Hoje vamos falar sobre uma ferramenta que cada vez mais quem trabalha com Docker acaba utilizando que é o Ansible. A primeira vista muitas pessoas acham que ambas ferramentas fazem a mesma coisa, apresentando uma solução para gerenciamento de configurações através de meios diferentes. Na realidade a união das duas ferramentas torna o ambiente de implantações de softwares limpo, confiável e rápido.

Ansible

É uma ferramenta de automatização de tarefas semelhante a Puppet e Chef, porém muito mais poderosa e a queridinha do pessoal DevOps hoje. Com ela é possível fazer o deploy de aplicações, provisionando de servidores, automatizar tarefas, e outras funções.

O Ansible trabalha com arquivos YAML,  o principal arquivo de configuração é chamado de PLAYBOOK onde você coloca todas as tarefas que serão executadas “yum”,”mkdir”,”useradd” e no arquivo .ini você adiciona os servidores onde o Ansible irá executar esse PLAYBOOK. Cada Playbook possui roles que são as informações de provisionamento, após definir as roles você definirá em quais hosts essas roles serão executadas.

Dentro das roles existem as tasks, handlers, variaveis e templates:

       – Tasks: Tarefas de provisionamento que serão executadas

       – Handlers: Tarefas para manipular serviços e arquivos.

       – Templates: Arquivos para serem transformados em configurações dentro das máquinas.

       – Variaveis: Valores que são definidos para serem usados dentro das tasks, handlers e templates

O Ansible é uma ferramenta muito mais simples que seus concorrentes citados anteriormente, já que ele não precisa que seja instalado agents nos servidores na qual ele irá executar.

É possível utilizar Docker e Ansible em conjuntos para resolver duas situações: Implantação de Containers e Criação de Imagens.

Implantação de containers: É possível fazer toda a parte de orquestração, configuração e provisionamento com containers, sem precisar fazer a instalação de agents dentro dos containers

Criação de Imagens:

Exemplo de Playbook:

# Mysql service name for drupal application
mysqlservice: mysqld

# Mysql port for drupal application
mysql_port: 3306

# Database name for the drupal application
dbname: databasename

# Mysql Username for drupal application
dbuser: root  

Exemplo de Configuração do arquivo do Ansible:

[defaults]
inventory = /etc/ansible/inventory
host_key_checking = False
priva_key_file = ~/.sh/id_rsa
callback_plugins   = /opt/ansible-plugins/callbacks
connection_plugins = /opt/ansible-plugins/connections

Então tá pessoal, hoje fizemos apenas uma pequena introdução ao Ansible, em nossos próximos posts estaremos trazendo algo como Jenkins, Travis e também faremos um grande post mostrando como podemos criar um ambiente com Docker, Jenkins e Ansible. Obrigado

Referência: http://docs.ansible.com/ansible/playbooks_intro.html e http://www.ibm.com/developerworks/br/cloud/library/cl-provision-docker-containers-ansible/

Persistindo dados – Flocker

Olá,

Hoje, no terceiro post da série: Persistindo dados, vamos abordar mais uma forma de como você pode persistir os dados de sua aplicação, garantindo maior disponibilidade para seu ambiente, hoje o assunto é sobre o Flocker.

 A proposta do Flocker é muito parecida com demais soluções para sistema de arquivos distribuídos, a grande diferença esta no foco que a ClusterHQ (desenvolvedora da solução) está dando para o projeto, pois o objetivo tem sido tornar o Flocker cada vez mais especializado em Docker, ou seja, o objetivo do Flocker não é atender a qualquer tipo de problema, mas sim, atender muito bem uma das deficiências que há no Docker , que é a persistência de dados, tanto que o Flocker em si já é um plugin de volumes oficial do Docker. Veja abaixo uma imagem que ilustra muito bem o que o Flocker se propõem a atender:

Fonte: https://clusterhq.com/flocker/introduction/

Atualmente, quando você instância um container em outro host, você precisa cuidar se o volume de onde está sua aplicação também tem mapeamento nesse novo host, o objetivo do Flocker abstrair esse tipo de preocupação, e garantir que, quando um container for movido de um lado para o outro, os dados que estavam mapeados nele também acompanhem esse movimento.

Veja abaixo como é a arquitetura dessa plugin:

Fonte: https://clusterhq.com/flocker/introduction/

Note que, diferentemente do GlusterFS, você precisa ter um ambiente mais complexo, envolvendo basicamente 3 camadas: Flocker Plugin, que é responsável pela comunicação entre o Docker e o Flocker; Flocker Conrol, responsável pelo monitoramento dos volumes, e controle sob o funcionamento do ambiente; Flocker Agent, responsável por executar as ações de criação, remoção e demais ações do Flocker no host que faz parte do ambiente.

Novamente, e o Docker?

Como já falamos em posts anteriores, a intenção não é mostrar a vocês como realizar a instalação e configuração do cluster de Flocker, e sim, seu uso final, juntamente com o Docker, talvez daqui a pouco possamos montar um material com isso ;).

Mãos a massa:

Primeiro vamos criar o volume Docker utilizando o plugin do Flocker, para isso:

$ docker volume create --name volume-1 -d flocker

Agora basta mapear esse volume criado aos containers que desejar:

$ docker run -v volume-1:/data -it centos /bin/bash

Basta criar algum arquivo ou pasta no diretório /data do container e essa informação será salva no volume Flocker que você criou, para ter certeza de que o dado estará nesse volume, crie outro container mapeando esse volume, e você verá que no /data desse novo container estará o arquivo/pasta que você criou no primeiro.

Fácil né? O mais interessante no Flocker é que você não perde os dados caso dê algum problema no host, o volume será criado no cluster Flocker que você montou, e isso é o que garante a disponibilidade da informação.

Por hoje era isso, espero que tenham gostado e tendo dúvidas nos avisem, e claro ajudem divulgando o Blog 😉

Abraço!

Persistindo dados – GlusterFS

Oi Pessoal,

Seguindo na sequência de posts sobre persistência de dados no Docker, hoje vamos ver como podemos utilizar um sistema de arquivos distribuídos para garantir a disponibilidade de sua aplicação dentro de containers.

Para quem não conhece, o GlusterFS é um sistema de arquivos distribuídos desenvolvido pela RedHat e mantido pela comunidade GlusterFS. Como ele funciona? O Gluster permite que você defina volumes compartilhados entre os hosts, isso faz com que os dados sejam distribuídos entre os nós que fazem parte desse volume, existem basicamente duas formas de distribuir os dados com o GlusterFS:

Distributed Glusterfs Volume

Nesse Formato, o GlusterFS distribuí os dados do volume entre todos os nós, isso quer dizer que cada nó terá apenas uma parte da informação, essa arquitetura é muito útil quando você deseja que a leitura seja muito rápida, pois o acesso é feito simultaneamente em todos os nós, mas não garante disponibilidade dos dados, pois caso um dos nós falhe, as informações que ele continha ficarão inacessíveis. Veja abaixo o desenho ilustrativo:

distributed_volume

Fonte: http://gluster.readthedocs.org/en/latest/Quick-Start-Guide/Architecture

Neste exemplo, quando for solicitado os arquivos File 1 e File 3, o Gluster consultará todos os nós e retornará a informação solicitada, como esse acesso é simultâneo, o tempo de resposta é reduzido.

Replicated Glusterfs Volume

No caso de se utilizar o método de replicação, os dados serão armazenados em todos os nóss, isso é claro aumenta o tempo de gravação do arquivo, pois o tempo de resposta será baseado no nó mais lento, mas garante disponibilidade da informação em caso de falha de algum outro nó. Veja abaixo como é esse tipo de arquitetura:

replicated_volume

Fonte: http://gluster.readthedocs.org/en/latest/Quick-Start-Guide/Architecture

Como ser visto, os arquivos são salvos sempre em todos os demais nós, a consulta é feita sempre no nó com menos latência, ou seja, o mais próximo do ponto de origem da requisição.

Há ainda uma forma mista de trabalho, onde é possível garantir que o dados seja replicado e que seja escrito em diversos nós, chama-se:

Distributed Replicated Glusterfs Volume

Dessa forma os dados são escritos em um volume distribuído, que possui ainda sub-volumes replicados, ou seja, você tem maior velocidade de leitura, e ainda garante que os dados estejam em vários nós ao mesmo tempo. Veja como isso funciona:

distributed_replicated_volume

Fonte: http://gluster.readthedocs.org/en/latest/Quick-Start-Guide/Architecture

Note que quando for salvo algum arquivo no ponto de montagem, ele salvará o arquivo no volume distribuído, e esse volume contém os sub-volumes replicados. Para todos os efeitos, o retorno da operação de gravação é realizado pelo volume distribuído, mas o dado será replicado entre os demais nós que fazem parte do volume replicado.

Ok, mas e o Docker?

O objetivo desse post não é ensiná-los a como instalar ou configurar o Gluster, mas sim, como utilizá-lo para garantir disponibilidade de seus dados. Pensando nisso, queremos mostrar para vocês como pode ser utilizado um plugins do Docker que provê suporte a GlusterFS, tenha em mente, antes de tudo, que você já deve ter seu cluster de GlusterFS montando e funcionando, independente da arquitetura escolhida ou ponto de montagem.

Passo 1:

Instale o plugin para administração dos volumes GlusterFS:

$ go get github.com/calavera/docker-volume-glusterfs
Passo 2:

Monte seu ambiente, informando quais servidores fazem parte do cluster que atenderá a demanda de volume, informe também em qual porta o serviço executará, caso esteja utilizando uma porta alternativa:

$ docker-volume-glusterfs -servers server1:server2:server3

É importante enfatizar que você precisará realizar esse procedimento em todos os hosts com Docker aos quais deseja utilizar esse plugin.

Passo 3:

Agora use!

$ docker run --volume-driver glusterfs --volume datastore:/teste centos touch /teste/ola

Inicie outro container, informando esses dados de volume e veja que foi criado um arquivo ola dentro da pasta teste:

$ docker run --volume-driver glusterfs --volume datastore:/teste centos /bin/bash
$ ls -la /teste/
$ -rw-r-xr-- 1 root root 1115 Apr 11 ola

O mais interessante é que nesse caso, você não precisa fazer com que os containers se falem diretamente, basta que nos hosts de Docker você inicie o plugin informando quais os hosts de GlusterFS que serão utilizados, feito isso é só mapear para o container e pronto, seus dados estarão sendo vistos por qualquer container que utilizar esse mesmo volume.

Gostou? Ajude divulgando o Blog 😉

Grande Abraço!

Persistindo dados -BTSync

Olá,

Hoje o mundodocker.com.br dará inicio a uma série de posts que tem por objetivo trazer soluções práticas para a persistência de dados no ambiente Docker.

Uma das premissas de se utilizar Docker é de que seu container é descartável, sim, isso pode parecer um tanto quanto radical, mas container em si foi desenvolvido para atender um processo durante um tempo determinado, e não para servir como um servidor virtual, nesse sentido, um cuidado que se deve ter é persistir os dados importantes de sua aplicação em um volume, ou até mesmo em um sistema de arquivo distribuído, dessa forma um container pode morrer, sem que sua aplicação morra junto.

Vamos ver nessa série, algumas alternativas para isso, e começamos com a mais simples delas: BTSync. Para quem não conhece o BTSync é uma ferramenta que utiliza o protocolo do Bittorrent para sincronismo de dados, através dele é possível sincronizar pastas e arquivos entre diferentes plataformas (desde que tenha o Sync instalado), de forma segura e rápida. No nosso exemplo vamos simular a sincronização de dados entre containers, dessa forma você pode fazer com que diversos containers tenha os dados de sua aplicação, garantindo assim maior disponibilidade. Mãos a obra então:

Como vocês já sabem, vamos criar um Dockerfile para gerarmos uma imagem e carrega-la para onde quisermos, esse é um bom exemplo:

FROM ubuntu:14.04

RUN apt-get update && apt-get install -y curl
RUN curl -o /usr/bin/btsync.tar.gz http://download-lb.utorrent.com/endpoint/btsync/os/linux-x64/track/stable; cd /usr/bin && tar -xzvf btsync.tar.gz && rm btsync.tar.gz
RUN mkdir -p /btsync/.sync; mkdir -p /var/run/btsync; mkdir -p /data

EXPOSE 8888
EXPOSE 55555

ADD start.sh /usr/bin/start.sh

RUN chmod +x /usr/bin/start.sh

VOLUME ["/data"]

ENTRYPOINT ["start.sh"]

 

Na mesma pasta onde está esse Dockerfile, crie um arquivo chamado: start.sh com o seguinte código:

#!/bin/bash
SECRET="${@}"
: ${SECRET:=`btsync --generate-secret`}

echo "Starting btsync with secret: $SECRET"

echo "{
 \"device_name\": \"Sync Server\",
 \"listening_port\": 55555,
 \"storage_path\": \"/btsync/.sync\",
 \"pid_file\": \"/var/run/btsync/btsync.pid\",
 \"check_for_updates\": false,
 \"use_upnp\": false,
 \"download_limit\": 0,
 \"upload_limit\": 0,
 \"shared_folders\": [
 {
 \"secret\": \"$SECRET\",
 \"dir\": \"/data\",
 \"use_relay_server\": true,
 \"use_tracker\": true,
 \"use_dht\": false,
 \"search_lan\": true,
 \"use_sync_trash\": false
 }
 ]
}" > /btsync/btsync.conf

btsync --config /btsync/btsync.conf --nodaemon

Explicando: Você pode definir, via arquivo de configuração, algumas variáveis para o btsync trabalhar, como por exemplo chave para estabelecer comunicação, diretório que será sincronizado e limites de transferência, é claro que em nosso teste não vamos definir algumas delas, apenas alterei o “dir” para que seja sincronizado o diretório /data, você pode definir qualquer um. Por padrão, a porta de comunicação é a 55555, você pode modificá-la sem problema, e não é necessário você mapear portas do host para o container ;).

Então, criado o Dockerfile e o start.sh, vamos gerar a imagem:

docker build -t bt_mundodocker .

Agora é simples, basta você iniciar o primeiro container:

docker run -d --name repl1 bt_mundodocker

Você deve capturar a chave gerada na inicialização desse container, ela será útil para quando você iniciar o segundo container, pois será a chave que permitirá estabilizar a conexão entre os peers do btsync:

docker logs repl1

A saída desse comando, será algo parecido com isso:

Starting btsync with secret: ANDHOU5F7NHNR3EBPFYBPFJJMKATGLBEK
[20160329 21:23:04.194] total physical memory 536870912 max disk cache 2097152
[20160329 21:23:04.195] My PeerID: 102D9BFD720DF686F77DD0BC7FE5FDC98C767930
[20160329 21:23:04.683] LC: license expired
[20160329 21:23:05.291] LC: license renewal

Basta você inicializar o segundo container, passando essa chave como parâmetro:

docker run -d --name repl2 bt_mundodocker ANDHOU5F7NHNR3EBPFYBPFJJMKATGLBEK

Veja agora o retorno do comando docker logs desse container:

Starting btsync with secret: ANDHOU5F7NHNR3EBPFYBPFJJMKATGLBEK
[20160329 21:27:07.480] total physical memory 536870912 max disk cache 2097152
[20160329 21:27:07.482] My PeerID: 1015FC44C961E6AB9B77AD3951437CC69C6D357A
[20160329 21:27:07.756] LC: license expired
[20160329 21:27:08.084] LC: license renewal
[20160329 21:27:08.090] PeerConnection[0x00007fe9bc001170] incoming connection from 172.17.0.42:57871
[20160329 21:27:08.143] PeerConnection[0x00007fe9bc001170] incoming connection from 172.17.0.42:57871
[20160329 21:27:09.260] PeerConnection[0x00007fe9bc20a1c0] incoming connection from 172.17.0.42:55555

Para testar, acesse os containers (docker exec -it repl1/repl2 /bin/bash), crie arquivos dentro da pasta /data e veja que eles serão sincronizados entre os containers, mesmo se você tiver mais de dois containers. Legal né? Todo o trafego entre os containers (mesmo os que não sejam locais) é criptografado, e apenas peers (containers) que iniciaram com a chave mencionada é que entram na replicação. Claro, nem tudo são flores, quanto maior a latência entre os containers, mais lento será essa replicação, então pense bem antes de sair utilizando ele para qualquer coisa 🙂

Fácil, simples e muito eficiente, essa foi a apresentação da primeira solução para persistência de dados entre os containers, fique atento aos próximos. Se gostou, ajude divulgando o Blog.

Grande Abraço!

Kubernetes parte I

Olá pessoal,

Hoje vamos iniciar uma série de posts demonstrado como podemos utilizar o Kubernetes como ferramenta de automatização, distribuição de carga, monitoramento e orquestração entre containers.

Kubernetes é um sistema de código aberto que foi desenvolvido pelo Google para gerenciamento de aplicativos em containers através de múltiplos hosts de um cluster. Tem como principal objetivo facilitar a implantação de aplicativos baseados em microservices. Ele foi baseado na experiência do Google de muitos anos trabalho com containers, adaptando o  para se trabalhar com Docker.

O Kubernetes foi muito útil para ser utilizado até o Docker Swarm 1.0, pois disponibilizava muitos recursos que o Docker não disponibilizava até aquele momento, entre eles: Balanceamento de carga e movimento de containers sem perda de dados.

A principal vantagem que se tem ao utilizar o Kubernetes é que você não está preso as limitações da API do Docker (O Problema do Swarm) você tem total liberdade já que o Kubernetes não foi desenvolvido especialmente para o Docker, você pode trocar a sua estrutura de Docker para Rockets (Containers no CoreOS). Você pode escolher a simplicidade do Swarm ou o poder do Kubernetes.

Dentro do Kubernetes possuímos alguns termos para determinadas funções:

Minions: É o nome dado para cada host do cluster.

Kubelet: Agente que roda nos hosts do cluster.

Pods: É a menor unidade dentro de um cluster, nada mais é do que containers rodando dentro de seu cluster de Kubernetes. Pode ser um container rodando nginx, php, apache, etc…

Replication Controller: É o responsável por manter um número determinado de pods em execução. No RC é onde você diz quantos containers de nginx, php, apache você desejá que fiquem rodando, caso um caia, o RC cria outra instância automaticamente.

Services: É o responsável por atrelar uma faixa de IP para um determinado RC. Para que cada vez que o RC crie uma nova instância de pod o mesmo inicie com um IP determinado pelo service.

Namespace: Com o namespace você pode dividir seu Cluster de Kubernetes em dois ambientes, Produção e Teste, podendo limitar os recursos computacionais para ambos.

No proximo post vamos mostrar como podemos instalar e configurar o kubernetes para que você use em seu ambiente da melhor maneira possível.

Docker Compose

Oi pessoal,

Seguindo nossa série de posts sobre as ferramentas do ecossistema Docker, hoje veremos um pouco mais sobre o Docker Compose, uma ferramenta que agilizar no deploy de seu ambiente, utilizando uma forma simples, claro e padronizada.

O Docker Compose é uma ferramenta para a criação e execução de múltiplos containers de aplicação. Com o Compose, você usar um arquivo do tipo yaml para definir como será o ambiente de sua aplicação e usando um único comando você criará e iniciará todos os serviços definidos.

Compose é ótimo para desenvolvimento, testes e homologação, bem como para melhorar seu fluxo de integração continua. Por exemplo:

  • Em ambiente de desenvolvimento: Você pode utilizar ele para simular todo o ambiente de produção, ou seja, precisando de serviço redis, php, mysql? Basta definir isso em um arquivo .yml e quando você executar o docker-compose up, todo esse ambiente está disponível para você, todas as dependências que sua stack precisa estará configurada e disponível para uso. Isso sem contar que este ambiente poderá ser isolado, sem depender ou prejudicar o trabalho dos demais da equipe.
  • Automação de testes: Uma das premissas básicas para desenvolvimento e integração continua é ter uma base de testes automatizada, isso para garantir qualidade e agilidade na entrega de novas releases de sua aplicação. Pensando nisso, você pode utilizar o docker compose para criar sua própria suite de testes, e precisando apenas executar um docker-compose up para testar os 50, 100, 200 requisitos que você definiu.

Para utilizar o docker-compose você precisa ter em mente que será necessário seguir essas três etapas:

  1. Definir o ambiente necessário para sua aplicação utilizando um Dockerfile (que pode ser reproduzido em qualquer lugar que tenha Docker instalado);
  2. Definir no arquivo .yml  quais serviços são essenciais para sua aplicação e a relação entre elas.
  3. Executar o comando docker-compose up para que seu ambiente seja criado e configurado.

Fácil certo? Vamos praticar?

Instalação

Bem simples, basta executar o seguinte comando (caso Linux), se você estiver utilizando em Windows via Docker ToolBox você já terá disponível o docker-compose. Vamos lá:

curl -L https://github.com/docker/compose/releases/download/1.5.2/docker-compose-`uname -s`-`uname -m`
\ > /usr/local/bin/docker-compose

Depois:

chmod +x /usr/local/bin/docker-compose

Compose eu escolho você

Vamos testar com um WordPress, é fácil:

  1. Criar um diretório de trabalho (mkdir /my-app);
  2. Faça download do WordPress: cd /my-app; curl https://wordpress.org/latest.tar.gz | tar -xvzf –
  3. Criar um arquivo Dockerfile com o seguinte código:
    FROM orchardup/php5
    ADD . /app
    
  4. Criar um arquivo my-app.yml com o código:
    web:
      build: .
      command: php -S 0.0.0.0:8000 -t /my-app
      ports:
        - "80:8000"
      links:
        - db
      volumes:
        - .:/my-app
    db:
      image: orchardup/mysql
      environment:
        MYSQL_DATABASE: wordpress
    
  5. Certifique-se de que seu wp-config esteja parecido com este:
    <?php
    define('DB_NAME', 'wordpress');
    define('DB_USER', 'root');
    define('DB_PASSWORD', '');
    define('DB_HOST', "db:3306");
    define('DB_CHARSET', 'utf8');
    define('DB_COLLATE', '');
    
    define('AUTH_KEY',         'put your unique phrase here');
    define('SECURE_AUTH_KEY',  'put your unique phrase here');
    define('LOGGED_IN_KEY',    'put your unique phrase here');
    define('NONCE_KEY',        'put your unique phrase here');
    define('AUTH_SALT',        'put your unique phrase here');
    define('SECURE_AUTH_SALT', 'put your unique phrase here');
    define('LOGGED_IN_SALT',   'put your unique phrase here');
    define('NONCE_SALT',       'put your unique phrase here');
    
    $table_prefix  = 'wp_';
    define('WPLANG', '');
    define('WP_DEBUG', false);
    
    if ( !defined('ABSPATH') )
        define('ABSPATH', dirname(__FILE__) . '/');
    
    require_once(ABSPATH . 'wp-settings.php');
    
  6. O que falta? docker-compose up no diretório onde você criou o Dockerfile e o  my-app.yml.

Agora é só acessar: http://ipdamaquina e prosseguir com a instalação do Woprdress normalmente, o que o Compose fez então? No passo 3 nós criamos um arquivo Dockerfile contendo a descrição da imagem que queremos criar e que será utilizada como base para o nosso ambiente, no passo 4 nós definimos qual era esse ambiente, veja que definimos 1 container para atender requisições web e 1 banco de dados, quando executamos o docker-compose up ele criará a imagem baseado no Dockerfile e criar os containers de serviços que definimos no my-app.yml. O mais legal, você pode quer escalar seu ambiente, ter mais containers web? docker-compose scale web=5 e o Compose criará e iniciará 5 containers do serviço web que definimos no my-app.yml.

Alguns dados importantes sobre o Docker Compose:

  • O Compose preserva todos os volumes atribuídos aos seus serviços, por exemplo, quando você executa o docker-compose up, se você já tiver algum outro container utilizando o volume informado, o Compose copiará o volume do container antigo para o novo container, sem perder nenhuma informação.
  • O Compose recriará apenas containers cujas configurações foras modificadas, caso contrário ele se baseará nas configurações que ele já tem armazenada em cache, isso é muito útil principalmente para provisionar e escalar seu ambiente de forma muito mais rápida.

Você ainda pode utilizar o Docker Compose juntamente com o Docker Machine e provisionar seu ambiente em qualquer lugar que precisar, isso é ainda mais útil para quem tem seu serviço de infraestrutura terceirizado com outros provedores (AWS, Digital Ocean, etc).

Gostou? Ótimo! nos ajude divulgando o MundoDocker, não gostou? Não tem problema, deixa seu feedback para que possamos melhorar cada vez mais 😉

 

Abraço!