Usando Docker no Windows 10 – Parte 4

Seguindo com nossa série de artigos sobre usar Docker no Windows 10, neste artigo vamos detalhar um pouco mais os recursos para criação de uma imagem Docker customizada.

Seguem os outros artigos da série:
Introdução ao Docker no Windows 10, onde abordamos a instalação e setup.
Uso de uma imagem oficial Apache Httpd para publicar páginas Web.
Uso de composição de containers para definição de uma infra-estrutura de containers.

Fontes:
http://developers.redhat.com/blog/2014/05/15/practical-introduction-to-docker-containers/
https://docs.docker.com/engine/tutorials/dockerimages/

O Dockerfile: Visão geral

O Dockerfile é um arquivo que define uma imagem Docker. Todas as imagens Docker presentes do Docker Explore tem um Dockerfile.

Por exemplo, segue Dockerfile da última versão (latest) do Nginx:

FROM debian:jessie

MAINTAINER NGINX Docker Maintainers "docker-maint@nginx.com"

ENV NGINX_VERSION 1.11.5-1~jessie

RUN apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 \
	&& echo "deb http://nginx.org/packages/mainline/debian/ jessie nginx" >> /etc/apt/sources.list \
	&& apt-get update \
	&& apt-get install --no-install-recommends --no-install-suggests -y \
						ca-certificates \
						nginx=${NGINX_VERSION} \
						nginx-module-xslt \
						nginx-module-geoip \
						nginx-module-image-filter \
						nginx-module-perl \
						nginx-module-njs \
						gettext-base \
	&& rm -rf /var/lib/apt/lists/*

# forward request and error logs to docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
	&& ln -sf /dev/stderr /var/log/nginx/error.log

EXPOSE 80 443

CMD ["nginx", "-g", "daemon off;"]

Com base no exemplo acima, vamos ver algumas opções do Dockerfile.
Linha 1 Definição da imagem de origem. A imagem não será criada do zero, mas sim a partir de uma outra imagem, a “debian:jessie”.
Linha 3 Indicação dos mantenedores dessa imagem.
Linha 5 Configuração de variável de ambiente, informando a versão do Nginx.
Linha 7 Execução de comandos no debian para instalar o Nginx na imagem (usando apt-get).
Linha 22 Execução de comandos no debian para encaminhar logs para os arquivos dentro do caminho /var/log/nginx/.
Linha 25 Exposição das portas 80 e 443 da imagem.
Linha 27 Definição do comando que será executado quando um container gerado a partir dessa imagem for iniciado.

Para informações sobre as opções para configuração do Dockerfile, acesse o link https://docs.docker.com/engine/reference/builder/.

E conforme já visto nos outros artigos dessa série, essa imagem definida pela Dockerfile pode ser referenciada tanto no comando docker como também no arquivo docker-compose.yml.

Criando um Dockerfile

Para criar o Dockerfile, você pode usar um editor simples. Mas recursos como auto-complete e highlight são sempre bem vindos. Aqui vamos usar o Visual Studio Code com a extensão Dockerfile and Docker Compose File (yml) Support:

vscode

Como exemplo, criaremos uma imagem Maven com JDK 1.8 para compilar projetos Java com Maven. Ao procurar no Docker Explore, veja que há várias imagens maven. Vamos selecionar a imagem 3.3.9-jdk-8. E para essa nova imagem, incluiremos o git via apt-get:

FROM maven:3.3.9-jdk-8

# Install software 
RUN apt-get install -y git

RUN mkdir /usr/src/app

WORKDIR /usr/src/app

CMD tail -f /dev/null

Notas:

  • Criei uma pasta /usr/src/app e definindo ela como pasta de trabalho (WORKDIR) que equivale ao comando cd.
  • Estou usando aqui o CMD na definição da imagem (comando executado quando o container inicia) para manter o container em execução. Isso porque, por padrão, quando um container é iniciado, ele executa o comando configurado para ele e finaliza quando o comando terminar. Pode-se também usar outro comando ou um script que mantenha o container em execução. No caso do Nginx acima, é usado o próprio servidor nginx.

Para criar a imagem, vamos para o Prompt (ou Powershell), acessar o diretório onde criamos o Dockerfile e executar a seguinte linha de comando:

C:\docker>docker build .
Sending build context to Docker daemon 50.26 MB
Step 1 : FROM maven:3.3.9-jdk-8
 ---> 7d77e2359e4b
Step 2 : RUN apt-get install -y git
 ---> Using cache
 ---> 98b7ab407302
Step 3 : RUN mkdir /usr/src/app
 ---> Using cache
 ---> 024747703e49
Step 4 : WORKDIR /usr/src/app
 ---> Using cache
 ---> 9ce13b80a47b
Step 5 : CMD tail -f /dev/null
 ---> Using cache
 ---> 4021ac9ebb2a
Successfully built 4021ac9ebb2a
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.

C:\docker>

Notas:

  • No meu caso a imagem foi criada a partir de outras imagens que eu tinha criado anteriormente (using cache). No seu caso pode ser necessário baixar imagens remotamente.
  • Para visualizar nossa imagem, executamos o comando docker images. O ID da imagem é citado no final. No meu caso é o 4021ac9ebb2a.

Agora vamos criar e iniciar um container a partir dessa imagem usando o comando docker create --name MyContainer [IMAGE_ID]. Meu [IMAGE_ID] é 4021ac9ebb2a.

C:\docker>docker create --name MyContainer 4021ac9ebb2a
fbe07a630e91414c8b2042b733a5b44b47db98811535aa1e82448f13d111c948

C:\docker>docker start MyContainer
MyContainer

C:\docker>

Depois disso, podemos usar o container para executar comandos. Para demonstração, vamos clonar um repositório Git com projeto Maven e compilar o projeto com Maven (por exemplo, o repositório https://github.com/imglib/imglib2):

C:\docker>docker exec MyContainer git clone https://github.com/imglib/imglib2.git .
C:\docker>docker exec MyContainer mvn

Os comandos acima serão executados dentro do WORKDIR que definidos no Dockerfile.

Terminado o processo, podemos agora executar, por exemplo, o comando Bash de forma interativa para acessar o conteúdo compilado pelo nosso container. E para copiar um determinado arquivo de dentro do container, usamos o comando docker cp direto do nosso host:

C:\docker>docker exec -it MyContainer bash
root@fbe07a630e91:/usr/sdoc  pom.xml  src  target
root@fbe07a630e91:/usr/src/app# cd target
root@fbe07a630e91:/usr/src/app/target# ls
classes                 imglib2-3.2.2-SNAPSHOT-tests.jar    maven-statuser    test-classes
generated-test-sources  imglib2-3.2.2-SNAPSHOT.jar          surefire-reports
root@fbe07a630e91:/usr/src/app/target# exit
exit

C:\docker>docker cp MyContainer:/usr/src/app/target/imglib2-3.2.2-SNAPSHOT.jar .

C:\docker>dir
 Volume in drive C is OSDisk
 Volume Serial Number is 34BB-56DE

 Directory of C:\docker

28/10/2016  11:07    >DIR>          .
28/10/2016  11:07    >DIR<          ..
28/10/2016  10:29               148 Dockerfile
27/10/2016  20:12           604.821 imglib2-3.2.2-SNAPSHOT.jar
               2 File(s)        604.969 bytes
               2 Dir(s)   7.781.826.560 bytes free

C:\docker>

Pronto! Criamos um container a partir de uma imagem Maven, baixamos nele um repositório Git, compilamos e depois pegamos o arquivo JAR gerado.

O Docker Hub: Subindo nossa imagem

Criamos aqui uma imagem personalizada e ainda executamos um container sobre a imagem. Podemos agora subir essas modificações direto no Docker Hub, usando nossa conta. Se você ainda não tem, crie uma conta no Docker Hub.

Depois disso, volte para a linha de comando para fazer login, usando a conta recém criada, através do comando docker login:

C:\docke>docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username (joaocunhaeld):
Password:
Login Succeeded

Agora temos que definir qual imagem queremos subir para nossa conta do Docker Hub. Podemos usar a imagem original ou ainda gerar uma imagem a partir das mudanças feitas no container que criamos, o MyContainer.

Para subir a imagem original precisamos definir uma tag (exemplo, my-maven-img:original) para a imagem e fazer push:

C:\docker>docker tag 4021ac9ebb2a my-maven-img

C:\docker>docker tag 4021ac9ebb2a joaocunhaeld/my-maven-img:original

C:\docker>docker push joaocunhaeld/my-maven-img:original
The push refers to a repository [docker.io/joaocunhaeld/my-maven-img]
5f85e80cd5ef: Pushed
f68ec8cbf3e2: Pushed
7e074b280d4a: Pushed
6339c6454299: Mounted from library/maven
a49358240350: Mounted from library/maven
3ab252edeedb: Mounted from library/maven
cafbf8599061: Mounted from library/maven
271ee5f59d19: Mounted from library/maven
294aa583a65a: Mounted from library/maven
c5bb6583fe2c: Mounted from library/maven
b376ebfc5566: Mounted from library/openjdk
33c3a104206a: Mounted from library/openjdk
149636c85012: Mounted from library/openjdk
f96222d75c55: Mounted from library/php
latest: digest: sha256:0bda230011b65ecf02a142f588a4446014bf9756b0003e00667ddeed421cb8a4 size: 3251

C:\docker>

A tag que usei foi my-maven-img:original para a conta joaocunhaeld.

Já para o container precisamos fazer um passo a mais que é o commit das mudanças feitas nele. Isso porque o container tem uma imagem gerada a partir da imagem original (como um branch) com modificações que realizamos no container. E essas modificações precisam ser confirmadas (commit) caso queiramos subir elas no repositório (caso contrário subiremos a imagem original). E para ver informações da nossa imagem, usar o comando docker images -a [USER]/[IMAGE-NAME]:

C:\docker>docker commit MyContainer
sha256:f03d50fafe814234e898b98c2149e12454ee1c9ca44fbdc51ac9282e975fa828

C:\docker>docker images -a joaocunhaeld/my-maven-img
REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
joaocunhaeld/my-maven-img   latest              f03d50fafe81        15 hours ago        704.2 MB
joaocunhaeld/my-maven-img   original            4021ac9ebb2a        16 hours ago        651.1 MB
C:\docker>

Notem que temos a imagem my-maven-img:original, criada através do container 4021ac9ebb2a e a imagem my-maven-img:latest gerada a partir do commit que fizemos do nosso container. Vamos agora confirmar as mudanças fazendo um novo push:

C:\docker>docker push joaocunhaeld/my-maven-img

E agora tanto a imagem original como latest (com as alterações que fizemos no container) são públicas e estão disponíveis no Docker Hub. E qualquer outra pessoa pode obter nossas imagens através do comado docker pull joaocunhaeld/my-maven-img. Se não especificar a versão, será obtido o latest.

Próximos Passos

Apresentei nesse artigo como criar uma imagem usando o Dockerfile e executar comandos em um container. Depois disso ainda subi tanto a imagem original como as mudanças feitas no container na minha conta do Docker Hub. Em um próximo artigo irei descrever como usar o Docker no Azure e criar um Docker Registry personalizado para manter suas imagens fora do domínio público.

E fiquem a vontade para sugerir exemplos para demonstrarmos aqui. Abraços e até a próxima.

2 comentários

  1. Veja, muito bom seus artigos, vc poderia agora falar sobre acessar docker pela rede local, configurar nat ou bridge, instalar tipo seafile, pois realmente não consegui, até instalei um servidor seafile no windows 10 pro, mas não consigo enxergar ele na rede pelo outro micro win7. Como faço para transformar de mode bridge pra overlay (eu acho) e dessa forma poder acessar de outro micro. Obrigado

    Curtir

  2. Voce poderia fazer a gentileza de mostrar como intalar um servidor seafile, acho até que eu consegui, mas o problema é que não consigo enxerga-lo na rede, tipo no meu note do win7. Acredito que configurar bridge ou overlay seja complexo, esse lance de ip estático também complica, ajuda ai por favor… Obrigado.

    Curtir

Deixe um comentário