├── README.md
├── assets
├── docker-banner-0.jpg
├── docker-banner-1.jpg
├── docker-banner-2.jpg
├── docker-banner-3.jpg
├── docker-banner-4.jpg
├── docker-banner-5.jpg
├── docker-banner.jpg
├── docker-hub.png
├── docker-run-node.gif
└── git-hello.gif
├── lvl.0.configure
└── README.md
├── lvl.1.containers
├── README.md
└── app
│ ├── index.html
│ ├── package.json
│ └── server.js
├── lvl.2.images
├── README.md
└── app
│ ├── Dockerfile
│ ├── index.html
│ ├── package.json
│ ├── server.js
│ └── start.sh
├── lvl.3.network
├── README.md
└── app
│ ├── Dockerfile
│ ├── index.html
│ ├── package.json
│ ├── server.js
│ └── start.sh
├── lvl.4.volumes
├── README.md
└── app
│ ├── Dockerfile
│ ├── index.html
│ ├── package.json
│ ├── server.js
│ └── start.sh
└── lvl.5.compose
├── README.md
└── app
├── Dockerfile
├── docker-compose.yaml
├── index.html
├── package.json
├── server.js
└── start.sh
/README.md:
--------------------------------------------------------------------------------
1 | # Oficina de Docker
2 |
3 | 
4 |
5 | Repositório da oficina de docker para a IV semana de informática do Centro de Ensino Superior do Seridó - CERES/UFRN.
6 |
7 | Utilizaremos um aplicativo web escrito em Node com o framework Express como base para fazer a conteinerização e mostrar as vatanges da estratégia de utilizar Docker no desenvolvimento, porém, **não será necessário conhecimentos em Node para fazer essa oficina**
8 |
9 | ## Recomendações
10 |
11 | 1. Faça o clone desse repositório com o comando ``git clone https://github.com/victorhundo/docker-guide.git`` e verifique os arquivos de configuração paralelamente com as instruções do material da oficina.
12 |
13 | 2. Para fazer essa oficina recomendamos que todos os comandos sejam **executados manualmente** no terminal do seu computador, é importante que no fim dessa oficina você saiba o que cada paramêtro faz.
14 |
15 | ## Levels
16 | Esse repositório é dividido em pequenos módulos que abordam funcionalidades diferentes do Docker. São eles:
17 |
18 | 0. [Lvl 0 - Configure](http://github.com/victorhundo/docker-ceres/tree/master/lvl.0.configure)
19 | 1. [Lvl 1 - Containers](http://github.com/victorhundo/docker-ceres/tree/master/lvl.1.containers)
20 | 2. [Lvl 2 - Images](http://github.com/victorhundo/docker-ceres/tree/master/lvl.2.images)
21 | 3. [Lvl 3 - Network](http://github.com/victorhundo/docker-ceres/tree/master/lvl.3.network)
22 | 4. [Lvl 4 - Volumes](http://github.com/victorhundo/docker-ceres/tree/master/lvl.4.volumes)
23 | 5. [Lvl 5 - Compose](http://github.com/victorhundo/docker-ceres/tree/master/lvl.5.compose)
24 |
--------------------------------------------------------------------------------
/assets/docker-banner-0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/victorhundo/docker-guide/98c22d8f2261089b1422d851b954e195e3cd7158/assets/docker-banner-0.jpg
--------------------------------------------------------------------------------
/assets/docker-banner-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/victorhundo/docker-guide/98c22d8f2261089b1422d851b954e195e3cd7158/assets/docker-banner-1.jpg
--------------------------------------------------------------------------------
/assets/docker-banner-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/victorhundo/docker-guide/98c22d8f2261089b1422d851b954e195e3cd7158/assets/docker-banner-2.jpg
--------------------------------------------------------------------------------
/assets/docker-banner-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/victorhundo/docker-guide/98c22d8f2261089b1422d851b954e195e3cd7158/assets/docker-banner-3.jpg
--------------------------------------------------------------------------------
/assets/docker-banner-4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/victorhundo/docker-guide/98c22d8f2261089b1422d851b954e195e3cd7158/assets/docker-banner-4.jpg
--------------------------------------------------------------------------------
/assets/docker-banner-5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/victorhundo/docker-guide/98c22d8f2261089b1422d851b954e195e3cd7158/assets/docker-banner-5.jpg
--------------------------------------------------------------------------------
/assets/docker-banner.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/victorhundo/docker-guide/98c22d8f2261089b1422d851b954e195e3cd7158/assets/docker-banner.jpg
--------------------------------------------------------------------------------
/assets/docker-hub.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/victorhundo/docker-guide/98c22d8f2261089b1422d851b954e195e3cd7158/assets/docker-hub.png
--------------------------------------------------------------------------------
/assets/docker-run-node.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/victorhundo/docker-guide/98c22d8f2261089b1422d851b954e195e3cd7158/assets/docker-run-node.gif
--------------------------------------------------------------------------------
/assets/git-hello.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/victorhundo/docker-guide/98c22d8f2261089b1422d851b954e195e3cd7158/assets/git-hello.gif
--------------------------------------------------------------------------------
/lvl.0.configure/README.md:
--------------------------------------------------------------------------------
1 | # Lvl. 0 - Configure
2 |
3 | 
4 |
5 | Antes de começar nossos estudos práticos sobre Docker é necessário configurar o ambiente para que possamos instalar-lo, além do docker, também vamos instalar o ``docker-compose`` que veremos no Lvl.5.
6 |
7 | Para essa oficina vamos utilizar uma máquina com Debian. Caso seu computador não seja esse sistema, acessem a [documentação oficial do docker](https://docs.docker.com/install/overview/) para saber os procedimentos de instalação em outras plataformas.
8 |
9 | ## Instalação
10 |
11 | ### Docker
12 |
13 | **1.** Instae os pacotes que permitem o apt usar repositórios com `https`.
14 |
15 | ```
16 | $ sudo apt-get install \
17 | apt-transport-https \
18 | ca-certificates \
19 | curl \
20 | gnupg2 \
21 | software-properties-common
22 | ```
23 |
24 | **2.** Adicione a chave GPG oficial do Docker
25 |
26 | ```
27 | $ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
28 | ```
29 |
30 | **3.** Adicione o repositório Docker no apt
31 |
32 | ```
33 | $ sudo add-apt-repository \
34 | "deb [arch=amd64] https://download.docker.com/linux/debian \
35 | $(lsb_release -cs) \
36 | stable"
37 | ```
38 |
39 | **4.** Instale o Docker!
40 |
41 | ```
42 | $ sudo apt-get update && sudo apt-get install docker-ce
43 | ```
44 |
45 | **5.** [opcional] Adicione um usuário que não seja o root a executar comandos docker. Será necessário fazer logout/login para que as mudanças sejam efetivadas.
46 |
47 | ```
48 | $ sudo usermod -aG docker $USER
49 | ```
50 |
51 | ### Docker compose
52 |
53 | **1.** Instale o ``pip``.
54 |
55 | ```
56 | $ sudo apt-get install python-pip
57 | ```
58 |
59 | **2.** Insale o Docker-compose
60 |
61 | ```
62 | $ sudo pip install docker-compose
63 | ```
64 |
65 | #### [Próximo -> Lvl 1 - Containers](http://github.com/victorhundo/docker-ceres/tree/master/lvl.1.containers)
66 |
--------------------------------------------------------------------------------
/lvl.1.containers/README.md:
--------------------------------------------------------------------------------
1 | # Containers
2 |
3 | 
4 |
5 | Agora que estamos com ambiente configurado para executar Docker e o docker-compose, está na hora de colocar a mão na massa!
6 |
7 |
8 | **Esse módulo é divido em:**
9 |
10 | 1. [Intrdução](#introdução)
11 | 2. [Hello World](#hello-world)
12 | 3. [Criando Containers](#criando-containers)
13 | 4. [Alguns Comandos Úteis](#comandos-Úteis)
14 | 5. [Primeiro Build com Containers](#Primeiro-Build)
15 |
16 | ## Introdução
17 |
18 | O docker é uma ferramenta para criar e gerenciar containers, que assim como o nome sugere, é um compartimento para armazenar e/ou transportar objetos, no nosso caso o compartimento é criado através de **virtualização** em que memoria e o processamento são separados para o uso do exclusivo do container.
19 |
20 | É importante frisar que container **não é uma máquina virtual**, os containers utiliza-se do próprio kernel da máquina hospedeira, enquanto as máquinas virtuais também virtualizam o kernel. Com containers é possivel **isolar bibliotecas e binários** dentro do mesmo SO sem a necessidade de virtualizar um novo sistema.
21 |
22 | 
23 |
24 | ## Hello World
25 |
26 | Para verificar que seu ambiente está configurado de forma correta, basta executar o seguinte comando abaixo, se aparecer a mensagem `Hello from Docker!` tudo ocorreu bem:
27 |
28 | ```
29 | docker run hello-world
30 | ```
31 | 
32 |
33 | Ao executar esse comando, nós chamamos o binário do docker, criamos um container a partir da opção ``run`` e dizemos que o container que será criado é da `imagem` ``hello-world:latest``. (vamos falar de imagens mais a frente).
34 |
35 | ## Criando Containers
36 |
37 | Vamos agora criar um container que seja mais útil e a partir dele analisar os principais comandos de criação de um container. Vamos criar um container do **Node**. Para isso executem:
38 |
39 | ```
40 | docker run -it node bash
41 | ```
42 |
43 | 
44 |
45 | Dessa vez criamos um cointaner passando o parametro ``-it`` além de adicionar um ``bash`` no final, o parametro it signifca que você ganhará um **terminal interativo** ao exectuar o container, caso você não coloque essa opção o container executará suas instruções e quando o **seu comando principal** terminar de executar ele irá morrer. O comando ``bash`` irá executar o comando do shell no container, então dessa forma conseguimos ter um **shell interativo dentro do container**.
46 |
47 | Reparem que o hostname foi alterado, nesse momento estou dentro do container ``node:latest``, para verificar isso eu executei o comando ``node -v`` que me retornou a versão 10.11, enquanto que na minha máquina, como também pode ser notado, utilizo a versão 8.9 do node.
48 |
49 | **O node que roda na minha máquina não tem relação nenhuma com o node do container**, com esse isolamento podemos trabalhar com diversos serviços que utilizam versões diferentes da mesma tecnologia sem que entrem em conflitos.
50 |
51 | Dentro do container, ao listar os processos que estão rodando com o comando ``ps`` vamos observar a seguinte saida:
52 |
53 | ```
54 | PID TTY TIME CMD
55 | 1 pts/0 00:00:00 bash
56 | 8 pts/0 00:00:00 ps
57 |
58 | ```
59 |
60 | Só existe 2 processos rodando: o ps que acabamos de executar e o bash que executamos na criação do container, nesse caso, o processo principal é o ``bash`` (podemos observar pelo pid), caso esse processo morra o container também irá morrer.
61 |
62 | Para sair do container **sem matar o processo principal** execute ``Ctrl-p + q``.
63 |
64 | ## Comandos Úteis
65 |
66 | Ao executar o útlimo comando que citamos acima, você terá o shell do seu computador de volta. Como você manteve o processo principal do container ainda rodando, significa que o container também está rodando!
67 |
68 | ### Listando Containers
69 | para verificar os containers que estão rodando na sua máquina execute o comando:
70 |
71 | ```
72 | docker ps
73 | ```
74 |
75 | A saida será algo como:
76 |
77 | ```
78 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
79 | 668698b20989 node "bash" 7 minutes ago Up 7 minutes kind_northcutt
80 | ```
81 |
82 | 1. **CONTAINER ID** - Identificador único do container.
83 | 2. **IMAGE** - Imagem que deu origem ao container.
84 | 3. **COMMAND** - Comando principal do container.
85 | 4. **CREATED** - Data na qual o container foi criado;
86 | 5. **STATUS** - Estado do container, pode ser: Up, ou Exited
87 | 6. **PORTS** - Portas de rede que o container está utilizando/expondo.
88 | 7. **NAMES** - O nome do container, para ser mais amigável de identificar no lugar do ID, na criação do container é possivel personalizar o nome com o para metro --name, por exemplo ``docker run --name My-Node -it node bash``
89 |
90 | ### Adicionando ou retirando arquivos do container
91 |
92 | Ainda utilizando o exemplo do container node que criamos **kind_northcutt** (node gerado automaticamente, provavelmente será outro nome no seu computador), vamos adicionar os arquivos que esta na pasta ``/lvl1.containers/app`` nesse repositório.
93 |
94 | A pasta ``app`` tem uma aplicação hello world em node, para tranferir os arquivos para dentro do container faça:
95 |
96 | ```
97 | docker cp app/ NOME_DO_CONTAINER:/opt/
98 | ```
99 |
100 | Como já dito, o `NOME_DO_CONTAINER` mudará de máquina pra máquina, verifique executando o comando ``docker ps`` já visto.
101 |
102 | ### Entrando no container
103 |
104 | Até agora apenas entramos no container na hora de sua criação, para que possamos voltar ao ambiente do container devemos executar o comando:
105 |
106 | ```
107 | docker exec -it NOME_DO_CONTAINER bash
108 | ```
109 |
110 | A opção **exec** é voltado pra executar comandos dentro do container, porém, utilizamos da mesma estratégia quando criamos o container: passamos o parametro de terminal interativo e chamamos o shell.
111 |
112 | Uma vez de volta ao container, acesse a pasta ``/opt/app`` em que copiamos os arquivos de `app`, os arquivos devem ser listados de forma parecida como abaixo:
113 |
114 | ```
115 | root@668698b20989:~# cd /opt/app
116 | root@668698b20989:/opt/app# ls
117 | index.html index.js style.css
118 | root@668698b20989:/opt/app#
119 | ```
120 |
121 | ## Primeiro Build
122 |
123 | Agora que estamos com os arquivos node dentro do nosso container, podemos executar o primeiro build dentro do container, para isso execute:
124 |
125 | ```
126 | npm install
127 | ```
128 |
129 | e para subir nosso servidor web:
130 |
131 | ```
132 | npm start
133 | ```
134 |
135 | Se tudo correu bem você terá a seguinte saida:
136 |
137 | ```
138 | root@668698b20989:/opt/app# npm start
139 |
140 | > node-hello-world@0.0.1 start /opt/app
141 | > node server.js
142 |
143 | App listening on port 3000
144 | Press Ctrl+C to quit.
145 | ```
146 |
147 | Agora pressione novamente ``Ctrl-p + q`` para sair do container **salvando o estado atual** e em seguida pare o container que criamos com o comando:
148 |
149 | ```
150 | docker stop NOME_DO_CONTAINER
151 | ```
152 |
153 | e em seguida o remova:
154 |
155 | ```
156 | docker rm NOME_DO_CONTAINER
157 | ```
158 |
159 | Nesse módulo aprendemos o que é um container, executamos comandos básicos do docker e fizemos o build e deploy de uma aplicação web simples, porém, tudo de forma manual. No próximo módulo vamos aprender como automatizar o processo de build e deploy da aplicação. Criaremos nossa própria imagem!
160 |
161 | #### [Próximo -> Lvl 2 - Images](http://github.com/victorhundo/docker-ceres/tree/master/lvl.2.images)
162 |
--------------------------------------------------------------------------------
/lvl.1.containers/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
--------------------------------------------------------------------------------
/lvl.1.containers/app/package.json:
--------------------------------------------------------------------------------
1 |
2 | {
3 | "name": "node-hello-world",
4 | "description": "Servidor web para oficina de Docker",
5 | "version": "0.0.1",
6 | "private": true,
7 | "license": "Apache Version 2.0",
8 | "author": "Victor Hugo",
9 | "scrips":{
10 | "start": "node index.js"
11 | },
12 | "engines": {
13 | "node": ">=4.3.2"
14 | },
15 | "dependencies": {
16 | "express": "^4.14.0"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/lvl.1.containers/app/server.js:
--------------------------------------------------------------------------------
1 | #!/bin/env node
2 | var express = require('express');
3 | var app = express();
4 | const PORT = process.env.PORT || 3000;
5 | app.get('/', function (req, res) {
6 | res.sendfile('./index.html');
7 | });
8 |
9 | // Start the server
10 | app.listen(PORT, () => {
11 | console.log(`App listening on port ${PORT}`);
12 | console.log('Press Ctrl+C to quit.');
13 | });
14 |
--------------------------------------------------------------------------------
/lvl.2.images/README.md:
--------------------------------------------------------------------------------
1 | # Images
2 |
3 | 
4 |
5 | **Esse módulo é divido em:**
6 |
7 | 1. [Intrdução](#introdução)
8 | 2. [Docker Hub](#docker-hub)
9 | 3. [Dockerfile](#dockerfile)
10 | 4. [Criando a Primeira Imagem](#primeira-imagem)
11 |
12 |
13 | ## Introdução
14 |
15 | No módulo anterior nós copiamos os arquivos que estava na pasta ``/lvl.1.containers/app`` no repositório para que fosse possivel fazer o build e o deploy da nossa aplicação web exemplo, essa prática não é recomendada porque para uma aplicação grande contém vários arquivos além de outros programas/bibliotecas que precisam está instaladas no **ambiente da aplicação.** A melhor forma de customizar o container com as configurações necessárias para que sua aplicação funcione da melhor forma possivel é através de **imagens.**
16 |
17 | ## Docker Hub
18 | Uma imagem docker é um container pré-configurado em que será utilizado como referencia **para criar containers**. No nosso exemplo, usamos a imagem **oficial** do Node, assim como containers, podemos visualizar as imagens que estão instaladas na nossa máquina digitando o comando:
19 |
20 | ```
21 | docker image ls
22 | ```
23 | A saida deve ser algo como:
24 |
25 | ```
26 | REPOSITORY TAG IMAGE ID CREATED SIZE
27 | node latest 8672b25e842c 10 days ago 674MB
28 | hello-world latest 4ab4c602aa5e 3 weeks ago 1.84kB
29 | ```
30 |
31 | As imagens são baixadas do [Docker Hub](https://hub.docker.com/) que é o "github dos containers", lá você poderá encontrar a imagem base para os seus serviços:
32 |
33 |
34 | 
35 |
36 | Na data em que esse documento foi escrito esses foram as principais imagens oficiais que estão no Docker Hub. Em cada repoistório de imagem, existe as instruções de como criar o container.
37 |
38 | ## Dockerfile
39 |
40 | Mesmo que no Docker Hub exista diversas soluções já desenvolvidas, você pode precisar de uma imagem específica da sua aplicação, uma imagem em que você e outras pessoas possam baixar e utilizar sua aplicação. Para isso é necessário criar um **Dockerfile**.
41 |
42 | Dentro da pasta ``/lvl.2.images/app/`` existe um arquivo chamadao ``Dockerfile``, nele terá as instruções para criar a imagem da nossa aplicação web exemplo.
43 |
44 | A primeira linha do Dockerfile diz qual será a imagem usada como base para criar a nossa própria imagem para isso usa-se o ``FROM``, no nosso caso será a imagem do Node na última versão disponível no Docker hub. Na segunda linha o ``LABEL`` adiciona meta dados à imagem, estamos colocando o nome de quem mantém essa imagem.
45 |
46 | Pedimos que **acessem o arquivo ./lvl.2.images/app/Dockerfile** e altere o ``LABEL`` para o seu nome e email.
47 |
48 | ### FROM/LABEL
49 | ```
50 | FROM node:latest
51 | LABEL maintainer "Victor Hugo "
52 | ```
53 | ### WORKDIR
54 | Logo em seguinda em ``WORKDIR`` que nos vai dizer em qual pasta estará nosso diretório de trabalho, ao acessar o container essa será a pasta padrão. Utilizar workdir é importante para não se preocupar em caminhos absolutos na hora de rodar scripts.
55 |
56 | ```
57 | WORKDIR /opt
58 | ```
59 | ### RUN
60 | Agora executaremos comandos de instalação no container, podemos executar qualquer comando usando ``RUN``. O primeiro executa a instalação do nmap e em seguida remove o cache gerado pelo apt, porque **o container deve ser efêmero e o mais leve possível**, o seguida instala o pacote ``nodemon`` do npm.
61 |
62 | ```
63 | RUN apt-get update && apt-get install -y \
64 | nmap \
65 | && rm -rf /var/lib/apt/lists/*
66 |
67 | RUN npm install -g nodemon
68 | ```
69 | ### EXPOSE
70 |
71 | ``EXPOSE`` está relacionada a rede do container, ele informará que a **porta 3000 do container estará exposta** , essa informação é importante para a próxima parte dessa oficina quando falaremos da rede no Docker.
72 |
73 | ```
74 | EXPOSE 3000
75 | ```
76 |
77 | ### COPY
78 | Em seguida copiamos os arquivos da nossa aplicação web exemplo que estão no mesmo diretório do Dockerfile e colocando na pasta ``/opt`` dentro do container (a pasta que é nosso diretório de trabalho). Para isso usamos ``COPY``.
79 |
80 | ```
81 | COPY ./* /opt/
82 | ```
83 |
84 | ### CMD
85 | Por fim ``CMD`` chamará o comando principal do container, no nosso caso escolhemos que fosse o shell script ``start.sh`` que está em ``/lvl.2.images/app/`` porque nos dá a liberdade de executar várias instruções, dentro de start.sh está os comandos ``npm install`` e ``npm start``. Se start.sh parar de executar o container também irá parar.
86 |
87 | ```
88 | CMD [ "bash", "/opt/start.sh"]
89 | ```
90 | ### Aprenda na prática
91 | Para aprender mais sobre Dockerfiles e aprender na prática, recomendamos o [repositório da Jessie Frazelle](https://github.com/jessfraz/dockerfiles), lá você encontrará inúmeros dockerfiles, inclusive que utilize interfaces gráficas ou que explorem redes como o container do Tor que ela fez.
92 |
93 | ## Primeira imagem
94 |
95 | Agora que aprendemos os conceitos e os caminhos para criar um Dockerfile, chegou a hora de montar nossa primeira imagem! Para isso entrem na pasta ``app`` desse módulo e executem:
96 |
97 | ```
98 | docker build . -t my_node:1
99 | ```
100 |
101 | Se tudo ocorreu bem, ao executamos ``docker images ls``, veremos que nossa imagem com a tag 1 foi criada.
102 |
103 | ```
104 | REPOSITORY TAG IMAGE ID CREATED SIZE
105 | my_node 1 828e3f079092 27 seconds ago 723MB
106 | node latest 8672b25e842c 11 days ago 674MB
107 | hello-world latest 4ab4c602aa5e 3 weeks ago 1.84kB
108 | ```
109 | Agora que temos a imagem da nossa aplicação web podemos criar um container a partir dela, pra isso executamos:
110 |
111 | ```
112 | docker run -d --name my_app my_node:1
113 | ```
114 | Dessa vez executamos utilizando o parametro "detached" -d, esse parametro é o oposto quando utilizamos -it, ele criará o container em "background", para visualizar as informações de criação do container execute:
115 |
116 | ```
117 | docker logs -f my_app
118 | ```
119 |
120 | Nesse módulo aprendemos os conceitos por trás da imagem do docker e criamos uma para a nossa aplicação web exemplo utilizando **Dockerfile**, porém ainda não acessamos nossa aplicação, no próximo módulo estudaremos a parte de rede dos containers e como fazer para acessar nossa aplicação web!
121 |
122 | #### [Próximo -> Lvl 3 - Network](http://github.com/victorhundo/docker-ceres/tree/master/lvl.3.network)
123 |
--------------------------------------------------------------------------------
/lvl.2.images/app/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:latest
2 | LABEL maintainer "Victor Hugo "
3 |
4 | WORKDIR /opt
5 |
6 | RUN apt-get update && apt-get install -y \
7 | nmap \
8 | && rm -rf /var/lib/apt/lists/*
9 |
10 | RUN npm install -g nodemon
11 |
12 | EXPOSE 3000
13 |
14 | COPY ./* /opt/
15 |
16 | CMD [ "bash", "/opt/start.sh"]
17 |
--------------------------------------------------------------------------------
/lvl.2.images/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Hello Docker World!
9 |
10 |
11 |
12 |
13 |
14 |
179 |
180 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
--------------------------------------------------------------------------------
/lvl.2.images/app/package.json:
--------------------------------------------------------------------------------
1 |
2 | {
3 | "name": "node-hello-world",
4 | "description": "Servidor web para oficina de Docker",
5 | "version": "0.0.1",
6 | "private": true,
7 | "license": "Apache Version 2.0",
8 | "author": "Victor Hugo",
9 | "scrips":{
10 | "start": "node index.js"
11 | },
12 | "engines": {
13 | "node": ">=4.3.2"
14 | },
15 | "dependencies": {
16 | "express": "^4.14.0"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/lvl.2.images/app/server.js:
--------------------------------------------------------------------------------
1 | #!/bin/env node
2 | var express = require('express');
3 | var app = express();
4 | const PORT = process.env.PORT || 3000;
5 | app.get('/', function (req, res) {
6 | res.sendfile('./index.html');
7 | });
8 |
9 | // Start the server
10 | app.listen(PORT, () => {
11 | console.log(`App listening on port ${PORT}`);
12 | console.log('Press Ctrl+C to quit.');
13 | });
14 |
--------------------------------------------------------------------------------
/lvl.2.images/app/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | npm install
4 | npm start
5 |
--------------------------------------------------------------------------------
/lvl.3.network/README.md:
--------------------------------------------------------------------------------
1 | # Network
2 |
3 | 
4 |
5 |
6 | **Esse módulo é divido em:**
7 |
8 | 1. [Drivers](#drivers)
9 | 2. [Portas](#portas)
10 | 3. [Conectando dois containers](#conectando-dois-containers)
11 |
12 | ## Drivers
13 | Uma das razões de que utilizar os serviços em containers ser tão poderoso é porque eles podem ser conectados entre si, os sistemas de rede do Docker são plugáveis usando **Drivers**, por padrão o Docker oferece 5 drivers:
14 |
15 | 1. Bridge - Esse é o driver que será usado caso você não especifique qual quer utilizar, esse driver criará uma rede específica para o container com comunicação com a rede da máquina real.
16 | 2. Host - Esse driver utilizará a mesma interface de rede da máquina real, logo, se o container utilizar a porta 80, por exemplo, será a porta 80 da máquina real.
17 | 3. Overlay - Utilizado para clusterização de containers.
18 | 4. Macvlan - Permite que o container receba um endereço MAC fazendo com que ele seja percebido como um despositivo físico.
19 | 5. none - Desabilita o uso de rede para o container.
20 |
21 | A escolha dos drivers é feito na criação do container usando o parametro ``--net``, por exemplo:
22 |
23 | ```
24 | docker run --net=host httpd:latest
25 | ```
26 |
27 | **Nessa oficina iremos utilizar apenas o driver bridge.**
28 |
29 | ## Portas
30 |
31 | Serviços em redes são acessados através de portas, páginas http (80), servidores de email (25), login remote (22), etc, precisam especificar além do enderço IP a porta de comunicação.
32 |
33 | A nossa aplicação web exemplo roda na ``porta 3000``, para que possamos ter acesso na nossa máquina real, devemos criar o container com o seguinte comando:
34 |
35 | ```
36 | docker run -d --name my_app -p 1915:3000 my_node:1
37 | ```
38 |
39 | Repare que agora nós adicionamos mais um parametro na criação do container, o parametro ``-p`` significa que ao escutar na máquina real na porta ``1915`` quem responderá é o serviço que está rodando na porta ``3000`` dentro do container. Utilizamos 1915 mas poderiamos utilizar qualquer outra porta.
40 |
41 |
42 | Modifique o comando acima, e no lugar de 1915 adicione a data do seu aniversáro
43 |
44 | E em seguida acesse em um navegador web o endereço http://localhost:DATA_ANIVERSARIO
45 |
46 | Repare que podemos subir inúmeros containers do mesmo serviços em portas diferentes, assim, além de isolar memória, processamento, biblioteca/binários, o Docker também isola a rede para o funcionamento do container.
47 |
48 | ## Conectando dois containers
49 |
50 | Até agora nós trabalhamos apenas com um container de aplicação web, mas geralmente uma apliação web também precisa de um banco de dados para funcionar, nós teríamos duas opções:
51 |
52 | 1. Instalar nosso banco de dados dentro do container da aplicação web
53 | 2. Criar um container apenas para o banco de dados
54 |
55 | A segunda opção é a melhor prática, porque adicionando o container junto com a aplicação web tornará o container muito pesado e irá tirar o foco do container de isolamento do serviço, então a ideia é **1 serviço para 1 container**.
56 |
57 | Utilizaremos a imagem oficial do Mysql para criar nosso container do BD, utilizando as instruções que tem no repositório no Docker Hub, fazemos:
58 |
59 | ```
60 | docker run -d --name bd -e MYSQL_ROOT_PASSWORD=senha mysql:latest
61 | ```
62 |
63 | O comando acima apresenta um **novo parametro** o ``-e`` criará uma variavel de ambiente dentro do container, nesse caso ``MYSQL_ROOT_PASSWORD``, que receberá o valor **"senha"**, variaveis de ambientes são utéis para personalizar pequenos ajustes na criação do container.
64 |
65 | Ao executar ``docker ps``, deverá mostrar nossos 2 containers:
66 |
67 | ```
68 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
69 | 20ce701cb413 mysql:latest "docker-entrypoint..." 5 seconds ago Up 3 seconds 3306/tcp, 33060/tcp bd
70 | 4f263e37bf9e my_node:1 "bash /opt/start.sh" 29 minutes ago Up 29 minutes 0.0.0.0:1915->3000/tcp my_app
71 | ```
72 |
73 | Para que possamos fazer com que nossa aplicação se conecte com o container do mysql, precisamos remover o container da nossa aplicação e recria-lo:
74 |
75 | Removendo:
76 | ```
77 | docker stop my_app
78 | docker rm my_app
79 | ```
80 |
81 | Recriando com conexão com o container do BD:
82 | ```
83 | docker run -d --name my_app -p 1915:3000 --link bd:my_bd my_node:1
84 | ```
85 |
86 | O parametro ``--link`` informa ``NOME_DO_CONTAINER:APELIDO``, "nome do container" é o nome do container que vamos fazer a conexão e o apelido é por qual nome dentro do container irá reconhece-lo. Para verificar se a conexão de certo, vamos acessar o container da aplicação:
87 |
88 | ```
89 | docker exec -it my_app bash
90 | ```
91 |
92 | E em seguida vamos executar o nmap, esse programa varre as portas diponiveis de um determinado host, no nosso caso será o container do banco de dados, assim:
93 |
94 | ```
95 | nmap my_bd
96 | ```
97 |
98 | A saida deve ser algo como:
99 | ```
100 | Nmap scan report for my_bd (172.17.0.3)
101 | Host is up (0.000027s latency).
102 | Not shown: 999 closed ports
103 | PORT STATE SERVICE
104 | 3306/tcp open mysql
105 | MAC Address: 02:42:AC:11:00:03 (Unknown)
106 |
107 | Nmap done: 1 IP address (1 host up) scanned in 1.63 seconds
108 | ```
109 | Repare que a porta padrão do mysql ``3306`` está aberta, logo, se nossa aplicação for fazer alguma consulta ao banco de dados poderá ser feito utulizando o "my_bd".
110 |
111 | #### [Próximo -> Lvl 4 - Volumes](http://github.com/victorhundo/docker-ceres/tree/master/lvl.4.volumes)
112 |
--------------------------------------------------------------------------------
/lvl.3.network/app/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:latest
2 | LABEL maintainer "Victor Hugo "
3 |
4 | WORKDIR /opt
5 |
6 | RUN apt-get update && apt-get install -y \
7 | nmap \
8 | && rm -rf /var/lib/apt/lists/*
9 |
10 | RUN npm install -g nodemon
11 |
12 | EXPOSE 3000
13 |
14 | COPY ./* /opt/
15 |
16 | CMD [ "bash", "/opt/start.sh"]
17 |
--------------------------------------------------------------------------------
/lvl.3.network/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Hello Docker World!
9 |
10 |
11 |
12 |
13 |
14 |
179 |
180 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
--------------------------------------------------------------------------------
/lvl.3.network/app/package.json:
--------------------------------------------------------------------------------
1 |
2 | {
3 | "name": "node-hello-world",
4 | "description": "Servidor web para oficina de Docker",
5 | "version": "0.0.1",
6 | "private": true,
7 | "license": "Apache Version 2.0",
8 | "author": "Victor Hugo",
9 | "scrips":{
10 | "start": "node index.js"
11 | },
12 | "engines": {
13 | "node": ">=4.3.2"
14 | },
15 | "dependencies": {
16 | "express": "^4.14.0"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/lvl.3.network/app/server.js:
--------------------------------------------------------------------------------
1 | #!/bin/env node
2 | var express = require('express');
3 | var app = express();
4 | const PORT = process.env.PORT || 3000;
5 | app.get('/', function (req, res) {
6 | res.sendfile('./index.html');
7 | });
8 |
9 | // Start the server
10 | app.listen(PORT, () => {
11 | console.log(`App listening on port ${PORT}`);
12 | console.log('Press Ctrl+C to quit.');
13 | });
14 |
--------------------------------------------------------------------------------
/lvl.3.network/app/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | npm install
4 | npm start
5 |
--------------------------------------------------------------------------------
/lvl.4.volumes/README.md:
--------------------------------------------------------------------------------
1 | # Volumes
2 |
3 | 
4 |
5 |
6 | **Esse módulo é divido em:**
7 |
8 | 1. [Introdução](#intrdução)
9 | 2. [Tipos de volumes](#tipos-de-volumes)
10 | 3. [Deixando BD persistente](#deixando-bd-persistente)
11 | 4. [Criando container para desenvolvimento](#criando-container-para-desenvolvimento)
12 |
13 |
14 | ## Introdução
15 | Até agora nós vimos maneiras de utilizar containers para pegar sistemas já desenvolvido e inicia-lo em um mambiente controlado, também vimos que a ideia do container é que seja efêmero. Então como fazer com que os containers salvem os dados gerados? A repsosta para essa pergunta é **utilizando volumes!**
16 |
17 | Ao criar um volume, os dados que estão nele serão montados em algum diretório especifico dentro do container, os volumes são salvos na máquina real, desta forma, garantimos a opersistencia dos dados já que eles ficam idepedente do container.
18 |
19 | ## Tipos de volumes
20 | Existe dois tipos de volume: com bind e sem bind, volumes com bind são utilizados quando você quer especificar o caminho da sua máquina onde estão os dados do container enquanto volumes sem bind esse trabalho é feito pelo próprio Docker.
21 |
22 | A criação do volume pode ser feito na criação do container utilizando o paramêtro ``-v``
23 |
24 | ```
25 | # Exemplo de criação de volume com bind
26 | -v /home/user/container_data:/opt/app
27 | ```
28 |
29 | ```
30 | # Exemplo de criação de volume sem bind
31 | -v /opt/app (volume sem bind)
32 | ```
33 |
34 | Normamelnte volumes com bind são utilizados quando é preciso **fazer modificações** nos dados frequentemente, ao alterar os dados na pasta da sua máquina real em que está fazendo o bind, os dados dentro do container também serão alterados. **Arquivos de configuração ou códigos de desenvolvimento** são exemplos de bons usos dese tipo de volume.
35 |
36 | Já os volume sem bind geralmente são utilizados quando queremos **apenas salvar as informações** e queremos apenas ler esses dados, **banco de dados** é um exemplo que pode utilizar esse tipo de volme.
37 |
38 | ## Deixando BD persistente
39 |
40 | Para que possamos deixar os dados do banco de dados persistene primeiro precisamos saber como que o seu sgbd armazena os dados. No nosso caso que estamos utilizando mysql, ele armazena os dados no caminho ``/var/lib/mysql``, então o que será necessário é apenas informar ao Docker que essa pasta será armazenada em um volume. No nosso exemplo será:
41 |
42 |
43 | ```
44 | docker run -d --name bd -e MYSQL_ROOT_PASSWORD=senha -v my_data:/var/lib/mysql mysql:latest
45 | ```
46 | Assim como com o parametro ``-p`` o parametro ``-v`` é dividido em duas partes pelo dois pontos. Em um volume sem bind que criamos agora a palavra antes dos dois pontos **my_data** é o nome do volume que estamos criando e a palavra depois dos dois pontos é o caminho que está dentro do container que queremos aramazenar.
47 |
48 | Execute o comando ``docker volume ls`` e verifique que existe um volume chamado my_data.
49 |
50 | ```
51 | DRIVER VOLUME NAME
52 | local my_data
53 | ```
54 |
55 | ## Criando container para desenvolvimento
56 |
57 | Assim como vimos que a melhor maneira de criar um volume para desenvolvimento é utilizando bind, vamos criar o container da nossa aplicação novamente da seguinte forma:
58 |
59 | ```
60 | docker run -d --name my_app -p 1915:3000 -v "$PWD"/app:/opt/ --link bd:my_bd my_node:1
61 | ```
62 |
63 | Acessem http://localhost:1915 para verificar que a aplicação está acessivel.
64 |
65 | Em seguinda edite o arquivo `lvl.4.volumes/app/index.html` localize o nome ``Make Anything with Docker.`` e subsituta para ``Make My Web App with Docker.``
66 |
67 | Atualize a página http://localhost:1915 e verifque as alterações, isso só foi possivél porque o arquivo dentro do container também foi modificado. Desta forma é possivel criar um ambiente docker para o desenvolvimento e não terá mais necessidade de configurar cada máquina para desenvolver a aplicação, basta ter Docker!
68 |
69 | #### [Próximo -> Lvl 5 - Docker Compose](http://github.com/victorhundo/docker-ceres/tree/master/lvl.5.compose)
70 |
--------------------------------------------------------------------------------
/lvl.4.volumes/app/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:latest
2 | LABEL maintainer "Victor Hugo "
3 |
4 | WORKDIR /opt
5 |
6 | RUN apt-get update && apt-get install -y \
7 | nmap \
8 | && rm -rf /var/lib/apt/lists/*
9 |
10 | RUN npm install -g nodemon
11 |
12 | EXPOSE 3000
13 |
14 | COPY ./* /opt/
15 |
16 | CMD [ "bash", "/opt/start.sh"]
17 |
--------------------------------------------------------------------------------
/lvl.4.volumes/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Hello Docker World!
9 |
10 |
11 |
12 |
13 |
14 |
179 |
180 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
--------------------------------------------------------------------------------
/lvl.4.volumes/app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "node-hello-world",
3 | "description": "Servidor web para oficina de Docker",
4 | "version": "0.0.1",
5 | "private": true,
6 | "license": "Apache Version 2.0",
7 | "author": "Victor Hugo",
8 | "scrips": {
9 | "start": "node index.js"
10 | },
11 | "engines": {
12 | "node": ">=4.3.2"
13 | },
14 | "dependencies": {
15 | "express": "^4.14.0"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/lvl.4.volumes/app/server.js:
--------------------------------------------------------------------------------
1 | #!/bin/env node
2 | var express = require('express');
3 | var app = express();
4 | const PORT = process.env.PORT || 3000;
5 | app.get('/', function (req, res) {
6 | res.sendfile('./index.html');
7 | });
8 |
9 | // Start the server
10 | app.listen(PORT, () => {
11 | console.log(`App listening on port ${PORT}`);
12 | console.log('Press Ctrl+C to quit.');
13 | });
14 |
--------------------------------------------------------------------------------
/lvl.4.volumes/app/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | npm install
4 | npm start
5 |
--------------------------------------------------------------------------------
/lvl.5.compose/README.md:
--------------------------------------------------------------------------------
1 | # Docker Compose
2 |
3 | 
4 |
5 | Como vocês puderam reparar, os comandos do docker só fazem crescer e fica ainda mais complexo quando precisamos utilizar mais de um container para fazer nosso serviço funcionar (é natural que mais de 3 containers trabalhem em conjunto para uma única aplicação).
6 |
7 | O Docker Compose veio para **simplificar e facilitar** a manutenção de múltiplos containers para uma unica aplicação.
8 |
9 | ## docker-compose.yaml
10 |
11 | O docker compose utiliza um arquivo no padrão yaml para poder configurar a criação dos containers. Dentro do arquivo ``/lvl.5.compose/app/`` existe um arquivo chamado **docker-compose.yaml**, vamos analisar as informações que estão neles, assim como foi feito no arquivo Dockerfile.
12 |
13 | ### version
14 |
15 | ```
16 | version: '3'
17 | ```
18 | Indica a versão que o arquivo do docker-compose.yaml vai criar os containers, se for utilizar outra versão, parametros diferentes será necessário. A versão 3 é a mais recente.
19 |
20 | ### services
21 | ```
22 | services:
23 | ```
24 |
25 | No docker compose, cada container é conhecido como serviço, no nosso caso, vamos iniciar 2: web e bd.
26 |
27 | ### image
28 |
29 | Reparem que no serviço de web temos a nossa imagem "myapp", caso ela não exista na máquina, será criada pelo Dockerfile que está no repositório, o docker-compose sabe disso por causa do parametro ``build: .`` o "ponto" signifca que o Dockerfile está no mesmo diretorio que o arquivo docker-compose.yaml
30 |
31 | No serviço do BD, não tem o parametro build, logo, se não tiver a imagem na sua máquina, ela será baixada pelo Docker Hub.
32 |
33 | ### container_name
34 |
35 | O nome do container é criado nesse parametro.
36 |
37 | ### volumes
38 |
39 | O volume com bind é feito no serviço web, da mesma forma com que é foi feito no módulo anterior, diferença apenas que não precisa dizer o path completo.
40 |
41 | O volume sem bind no serviço do bd, é descrito qual volume será utilizado. Nesse caso, o volume é descrito depois de "services".
42 |
43 |
44 | ## Criando vários containers ao mesmo tempo
45 |
46 | Para criar os containers, basta entrar na pasta ``/lvl.5.compose/app`` e executar o comando
47 |
48 | ```
49 | docker-compose up
50 | ```
51 |
52 | ## Removendo vários containers ao mesmo tempo
53 |
54 | Para remover os containers basta executar
55 |
56 | ```
57 | docker-compose down
58 | ```
59 |
--------------------------------------------------------------------------------
/lvl.5.compose/app/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:latest
2 | LABEL maintainer "Victor Hugo "
3 |
4 | WORKDIR /opt
5 |
6 | RUN apt-get update && apt-get install -y \
7 | nmap \
8 | && rm -rf /var/lib/apt/lists/*
9 |
10 | RUN npm install -g nodemon
11 |
12 | EXPOSE 3000
13 |
14 | COPY ./* /opt/
15 |
16 | CMD [ "bash", "/opt/start.sh"]
17 |
--------------------------------------------------------------------------------
/lvl.5.compose/app/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | web:
4 | image: my_node:1
5 | build: .
6 | container_name: myWeb-app
7 | links:
8 | - bd:my_bd
9 | volumes:
10 | - ./:/opt/
11 | ports:
12 | - "1915:3000"
13 |
14 | bd:
15 | image: mysql:latest
16 | container_name: bd
17 | restart: always
18 | environment:
19 | - MYSQL_ROOT_PASSWORD=senha
20 | volumes:
21 | - datavolume:/var/lib/mysql
22 |
23 | volumes:
24 | datavolume:
25 |
--------------------------------------------------------------------------------
/lvl.5.compose/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Hello Docker World!
9 |
10 |
11 |
12 |
13 |
14 |
179 |
180 |