-
Notifications
You must be signed in to change notification settings - Fork 0
/
Docker_dia2
865 lines (605 loc) · 41.2 KB
/
Docker_dia2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
====================================================================
Docker
Instalando docker
curl -fsSL https://get.docker.com | bash
Adicionado o usuário no grupo do docker OBS: não pode estar logado com root
dockerd-rootless-setuptool.sh install
subir um container do hello world
docker container run hello-world
Lista os containers em execução
docker container ls
Lista todos os container até mesmo os que já se foram
docker container ls -a
Ativar um container para que fique em execução
docker container run -it ubuntu (aonde i=interatividade e t=terminal, rodando esse comando vc irá entrar direto no container) OBS: nesse caso não foi supracitado a versão desejada, mas quando for real a ação sempre importante frizar a versão desejada assim evitando supresas hehehe
Para sair do container pressione Ctrl + D, mas esse caso ira matar o container criado, no caso matou o bash que o principal processo em execução
Para sair do container sem matar o mesmo pressione Ctrl + p + q.
Assim quando executar o o comando:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0b598153f046 ubuntu "/bin/bash" 41 seconds ago Up 40 seconds vigilant_mors
Irá retornar o container que vc iniciou.
Acessar o container em execução
docker container attach 0b598153f046 ( aonde 0b598153f046 é o CONTAINER ID, que vc pega ao executaro comando docker ps) OBS: esse comando só funcionar se tiver rodando o bash no container, pq se fizer isso no ngnix não ira funcionar
Comando para pausar o container
docker container pause vigilant_morse (aonde vigilant_morse é o nome do container)
Comando para despausar o container
docker container unpause vigilant_morse
Remover um container
docker container stop vigilant_morse
docker container rm vigilant_morse apaga geral
Pegar informações dos containers em execução (cpu e memória de cada um)
docker container stats (use o parametro -a para ver tds os containers, até os excluídos)
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
754943a37b59 obivas2 0.00% 896KiB / 15.52GiB 0.01% 866B / 0B 0B / 0B 1
25361c2d5344 obivas1 0.00% 4.473MiB / 15.52GiB 0.03% 1.09kB / 0B 0B / 0B 1
Comando para mostrar como esta o uso de cpu e memrória do container, mas não fica preso a tela
docker container stats --no-stream
COmando para demonstrar o uso de memória com o DD
dd if=/dev/zero of=catota.img bs=8k count=2560k
Comando breve para ver os processos do container
docker container top obivas1
Comando para visualizar logs do container
docker container logs --details obivas1
COmando para listar as imagens utilizadas nos containers
docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest ca2b0f26964c 2 weeks ago 77.9MB
hello-world latest d2c94e258dcb 10 months ago 13.3kB
Apagar uma imagem
docker image rm d2c94e258dcb (certifiquese que a imagem não esteja em uso)
Forças a exclusão do container
docker container rm -f d2c94e258dcb (aonde -f é force)
Comando para trazer informações do container
docker inspect obivas1
Comando para iniciar um container sem necessáriamente entrar no mesmo na hora
docker container run -d --name obivas5 nginx (usamos o -d e a imagem do ngnix)
docker container run -d --name obivas5 -p 80:80 nginx (porta 80)
Acessar o containers do nginx
docker exec -it obivas bash
Comando para baixar uma imagem
docker pull centos:7
=====================================================================
Criando e administrando containers Docker
Como todos sabemos, o Docker utiliza a linha de comando para que você possa interagir com ele -- basicamente você utiliza o comando "docker".
Bom, agora que já iniciamos o Docker, vamos rodar nosso primeiro container.
Como é de costume quando alguém está aprendendo uma nova linguagem de programação, é bem comum fazer como o primeiro código um hello world!
Apesar de o Docker não ser uma linguagem de programação, vamos utilizar esse costume com o nosso primeiro exemplo de um container em execução.
O Docker possui uma imagem personalizada de hello-world e serve para que você possa testar a sua instalação e validar se tudo funciona conforme o esperado. :D
Para que possamos executar um container, utilizamos o parâmetro "run" do subcomando "container" do comando "docker". Simples, não? :D
root@linuxtips:~# docker container run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
03f4658f8b78: Pull complete a3ed95caeb02: Pull complete
Digest: sha256:8be990ef2aeb16dbcb9271ddfe2610fa6658d13f6dfb8bc72074cc1ca36966a7
Status: Downloaded newer image for hello-world:latest
Hello from Docker.
This message shows that your installation appears to be working correctly.
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker Hub account:
https://hub.docker.com
For more examples and ideas, visit:
https://docs.docker.com/userguide/
root@linuxtips:~#
No exemplo anterior, estamos executando um container utilizando a imagem personalizada do hello-world.
Apesar de ser uma tarefa simples, quando você executou o comando "docker container run hello-world" foram necessárias quatro etapas para sua conclusão, vamos ver quais:
O comando "docker" se comunica com o daemon do Docker informando a ação desejada.
O daemon do Docker verifica se a imagem "hello-world" existe em seu host; caso ainda não, o Docker faz o download da imagem diretamente do Docker Hub.
O daemon do Docker cria um novo container utilizando a imagem que você acabou de baixar.
O daemon do Docker envia a saída para o comando "docker", que imprime a mensagem em seu terminal.
Viu? É simples como voar! :)
Muito bem, agora que nós já temos uma imagem em nosso host, como eu faço para visualizá-la?
Muito simples, basta digitar o seguinte comando:
root@linuxtips:~# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest 690ed74de00f 5 months 960 B
root@linuxtips:~#
Como você pode notar no código, a saída traz cinco colunas:
REPOSITORY -- O nome da imagem.
TAG -- A versão da imagem.
IMAGE ID -- Identificação da imagem.
CREATED -- Quando ela foi criada.
SIZE -- Tamanho da imagem.
Quando executamos o comando "docker container run hello-world", ele criou o container, imprimiu a mensagem na tela e depois o container foi finalizado automaticamente, ou seja, ele executou sua tarefa, que era exibir a mensagem, e depois foi finalizado.
Para ter certeza de que ele realmente foi finalizado, digite:
root@linuxtips:~# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORT NAMES
root@linuxtips:~#
Com o "docker container ls", você consegue visualizar todos os containers em execução e ainda obter os detalhes sobre eles. A saída do "docker container ls" é dividida em sete colunas; vamos conhecer o que elas nos dizem:
CONTAINER ID -- Identificação única do container.
IMAGE -- A imagem que foi utilizada para a execução do container.
COMMAND -- O comando em execução.
CREATED -- Quando ele foi criado.
STATUS -- O seu status atual.
PORTS -- A porta do container e do host que esse container utiliza.
NAMES -- O nome do container.
Uma opção interessante do "docker container ls" é o parâmetro "-a".
root@linuxtips:~# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6e45cf509282 hello-world "/hello" 4 seconds Exited(0) tracted_ardinghelli
root@linuxtips:~#
Com a opção "-a" você consegue visualizar não somente os containers em execução, como também containers que estão parados ou que foram finalizados.
Legal, quero mais!
Agora que vimos como criar um simples container, bem como visualizar as imagens e containers que estão em nosso host, vamos criar um novo, porém conhecendo três parâmetros que irão trazer maior flexibilidade no uso e na administração de nossos containers. Estou falando dos parâmetros "-t", "-i" e "-d".
-t -- Disponibiliza um TTY (console) para o nosso container.
-i -- Mantém o STDIN aberto mesmo que você não esteja conectado no container.
-d -- Faz com que o container rode como um daemon, ou seja, sem a interatividade que os outros dois parâmetros nos fornecem.
Com isso temos dois modos de execução de nossos containers: modo interativo ou daemonizando o container.
Modo interativo
Na maior parte das vezes você vai subir um container a partir de uma imagem que já está pronta, toda ajustadinha. Porém, há alguns casos em que você precisa interagir com o seu container -- isso pode acontecer, por exemplo, na hora de montar a sua imagem personalizada.
Nesse caso, usar o modo interativo é a melhor opção. Para isso, basta passar os parâmetros "-ti" ao comando "docker container run".
Daemonizando o container
Utilizando o parâmetro "-d" do comando "docker container run", é possível daemonizar o container, fazendo com que o container seja executado como um processo daemon.
Isso é ideal quando nós já possuímos um container que não iremos acessar (via shell) para realizar ajustes. Imagine uma imagem já com a sua aplicação e tudo que precisa configurado; você irá subir o container e somente irá consumir o serviço entregue por sua aplicação. Se for uma aplicação web, basta acessar no browser passando o IP e a porta onde o serviço é disponibilizado no container. Sensacional, não?
Ou seja, se você quer subir um container para ser utilizado como uma máquina Linux convencional com shell e que necessita de alguma configuração ou ajuste, utilize o modo interativo, ou seja, os parâmetros "-ti".
Agora, se você já tem o container configurado, com sua aplicação e todas as dependências sanadas, não tem a necessidade de usar o modo interativo -- nesse caso utilizamos o parâmetro "-d", ou seja, o container daemonizado. Vamos acessar somente os serviços que ele provê, simples assim. :D
Entendi, agora vamos praticar um pouco?
Perfeito. Vamos iniciar um novo container utilizando dois desses novos parâmetros que aprendemos.
Para o nosso exemplo, vamos subir um container do Centos 7:
root@linuxtips:~# docker container run -ti centos:7
Unable to find image 'centos:7' locally
7: Pulling from library/centos
a3ed95caeb02: Pull complete 196355c4b639: Pull complete
Digest: sha256:3cdc0670fe9130ab3741b126cfac6d7720492dd2c1c8ae033dcd77d32855bab2
Status: Downloaded newer image for centos:7
[root@3c975fb7fbb5 /]#
Como a imagem não existia em nosso host, ele começou a baixar do Docker Hub, porém, caso a imagem já estivesse em nosso host, ele a utilizaria, não sendo necessário o download.
Perceba que mudou o seu prompt (variável $PS1), pois agora você já está dentro do container. Para provar que estamos dentro do nosso container Centos, execute o seguinte comando:
[root@3c975fb7fbb5 /]# cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
[root@3c975fb7fbb5 /]#
O arquivo "/etc/redhat-release" indica qual a versão do Centos que estamos utilizando, ou seja, estamos realmente em nosso container Centos 7. :D
Tá, agora quero sair...
Idealmente, no container vai haver apenas um processo rodando. No nosso caso, como estamos interagindo (opção "-ti"), é o processo do bash; logo, você não pode utilizar o comando "exit" para sair do console, pois dessa forma esse único processo para de rodar e seu container morre. Caso queira sair do container e mantê-lo em execução, é necessário sair com o seguinte atalho do teclado:
mantenha o botão Ctrl pressionado + p + q
Assim, você sairá do container e ele continuará em execução. Para confirmar se o container continua em execução, faça:
root@linuxtips:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3c975fb7fbb5 centos:7 "/bin/bash" 2 minutes Up 2 minutes angry_wescoff
root@linuxtips:~#
Posso voltar ao container?
Deixamos o nosso container em execução e agora queremos acessá-lo novamente. Como podemos fazer?
Simples! Basta digitar o seguinte comando:
root@linuxtips:~# docker container attach <CONTAINER ID>
O parâmetro "attach" do comando "docker container" possibilita nos conectarmos a um container em execução. Para isso, basta passar como parâmetro o "CONTAINER ID", que você consegue através da saída do "docker ps", conforme mostramos no exemplo anterior.
Continuando com a brincadeira...
Existe a possibilidade de criar um container, porém não o executar imediatamente. Quando fazemos o uso do parâmetro "create" do comando "docker container", ele apenas cria o container, não o inicializando, conforme notamos no exemplo a seguir:
root@linuxtips:~# docker container create -ti ubuntu
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
5a132a7e7af1: Pull complete
fd2731e4c50c: Pull complete
28a2f68d1120: Pull complete
a3ed95caeb02: Pull complete
Digest:sha256:4e85ebe01d056b43955250bbac22bdb8734271122e3c78d21e55ee235fc6802d
Status: Downloaded newer image for ubuntu:latest3e63e65db85a6e36950959dc6bdc00279e2208a335580c478e01723819de9467
root@linuxtips:~#
Perceba que quando você digita "docker container ls" ele não traz o container recém-criado, afinal a saída do "docker container ls" somente traz os containers em execução. Para visualizar o container recém-criado foi necessário utilizar o parâmetro "-a".
root@linuxtips:~# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3e63e65db85a ubuntu "/bin/bash" 18 seconds ago Created elo_visves
root@linuxtips:~#
Para que o nosso container recém-criado seja executado, basta utilizar o "docker container start [CONTAINER ID]", conforme segue:
root@linuxtips:~# docker container start [CONTAINER ID]
root@linuxtips:~# docker container attach [CONTAINER ID]
root@b422f04df14c:/#
Verificando se estamos realmente utilizando o container do Ubuntu:
root@b422f04df14c:/# cat /etc/issue
Ubuntu 18.04 LTS \n \l
root@b422f04df14c:/#
Lembrando que para sair do container e mantê-lo em execução é necessário utilizar o atalho: Ctrl + p + q.
Subindo e matando containers...
Caso eu queira parar um container em execução, basta utilizar o parâmetro "stop" seguido do "CONTAINER ID":
# docker container stop [CONTAINER ID]
Verificando se o container continua em execução:
# docker container ls
Lembrando que para visualizar os containers que não estão em execução é necessário utilizar o parâmetro "-a".
Para colocar novamente em execução um container que está parado, é necessário utilizar o parâmetro "start" do comando "docker container" seguido do "CONTAINER ID":
# docker container start [CONTAINER ID]
Da mesma forma como podemos utilizar o stop/start para desligar/iniciar um container, podemos também fazer o uso do "restart", como notamos a seguir:
# docker container restart [CONTAINER ID]
Para pausar um container, execute:
# docker container pause [CONTAINER ID]
E verifique o status do container:
root@linuxtips:~# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b34f4987bdce ubuntu "/bin/bash" 12 seconds ago Up 11 seconds (Paused) drunk_turi
root@linuxtips:~#
Para "despausar" o container:
# docker container unpause [CONTAINER ID]
Visualizando o consumo de recursos pelo container...
Caso você queira visualizar informações referentes ao consumo de recursos pelo container, também é bastante simples: basta utilizar o parâmetro "stats" para verificar o consumo de CPU, memória e rede pelo container em tempo real.
# docker container stats [CONTAINER ID]
CONTAINER CPU% MEM USAGE/LIMIT MEM % NET I/O BLOCK I/O PIDS
b34f4987bdce 0.00% 503.8kB/2.094GB 0.02% 648B/648B 0B/0B 2
Para sair, pressione Ctrl + C.
Para visualizar todos os containers de uma só vez, basta não especificar o [CONTAINER ID],conforme segue:
# docker container stats
Agora, se você quer visualizar quais processos estão em execução em determinado container, utilize o parâmetro "top". Com ele você consegue informações sobre os processos em execução, como, por exemplo, UID e o PID do processo.
# docker container top [CONTAINER ID]
UID PID PPID C STIME TTY TIME COMMAND
root 10656 4303 0 20:24 pts/3 00:00:00 /bin/bash
Para verificar os logs de um determinado container, utilize o parâmetro "logs", simples assim. :D
# docker container logs [CONTAINER ID]
Lembre-se: ele exibe o STDOUT, a saída padrão. Ou seja, normalmente você irá visualizar o histórico de mensagens que aparecerem em primeiro plano durante a execução do container.
Para exibir os logs de forma dinâmica, ou seja, conforme aparecem novas mensagens ele atualiza a saída no terminal utilizamos a opção "-f"
# docker container logs -f [CONTAINER ID]
. Com isso seu terminal ficará travado, apenas escutando o log, e qualquer nova entrada ele exibirá na tela. Saída parecida com o "tail -f" no Linux. Lembre-se, utilize o ctrl+c para cancelar a exibição dos logs.
Cansei de brincar de container, quero removê-lo!
Bem, remover um container é mais simples ainda do que sua criação. Quando removemos um container, a imagem que foi utilizada para a sua criação permanece no host; somente o container é apagado.
root@linuxtips:~# docker container rm b34f4987bdce
Failed to remove container (b34f4987bdce): Error response from daemon:
Conflict, You cannot remove a running container. Stop the container
before attempting removal or use -f
root@linuxtips:~#
Perceba que, quando você tentou remover o container, ele retornou um erro dizendo que falhou em remover, pois o container estava em execução. Ele inclusive recomenda que você pare o container antes de removê-lo ou então utilize a opção "-f", forçando assim sua remoção.
root@linuxtips:~# docker container rm -f b34f4987bdce
b34f4987bdce
root@linuxtips:~#
Para confirmar a remoção do container, utilize o comando "docker container ls -a".
====================================================
DockerFile
Criação de imagem de cointeiner.
FROM ubuntu:18.04
RUN apt-get update && apt-get install nginx -y
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Após criação do dockerfile, comando para subir o container usando o dockerfile criado
primeiro add a imagem criado
docker image build -t obivas01:1.0 .
Segundo subindo o container
docker container run -d -p 8080:80 --name obivas3 obivas01:1.0
Continuando aula sobre docker file, criamos um novo dockerfile
FROM ubuntu:18.04
RUN apt-get update && apt-get install nginx -y
EXPOSE 80
COPY index.html /var/www/html/
CMD ["nginx", "-g", "daemon off;"]
WORKDIR /var/www/html
ENV APP_VERSION 1.0.0
Novo dockerfile
FROM ubuntu:18.04
LABEL maintainer="[email protected]"
RUN apt-get update && apt-get install nginx -y
EXPOSE 80
COPY index.html /var/www/html/
WORKDIR /var/www/html
ENV APP_VERSION 1.0.0
ENTRYPOINT ["nginx"] ##principal processo do meu container
CMD ["-g", "daemon off;"] ##parametros do entrypoint
Novo docker file
FROM ubuntu:18.04
LABEL maintainer="[email protected]"
RUN apt-get update && apt-get install nginx curl -y
EXPOSE 80
ADD https://github.com/prometheus/node_exporter/releases/download/v1.6.0/node_exporter-1.6.0.linux-amd64.tar.gz /root/node-exporter
COPY index.html /var/www/html/
WORKDIR /var/www/html
ENV APP_VERSION 1.0.0
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
HEALTHCHECK --timeout=2s CMD curl -f localhost || exit 1
FROM ubuntu:18.04
LABEL maintainer="lucas"
RUN apt-get update && apt-get install nginx curl -y && rm -rf /var/lib/apt/lists/*
EXPOSE 80
ADD node_exporter-1.6.0.linux-amd64.tar.gz /root/node-exporter
COPY index.html /var/www/html/
WORKDIR /var/www/html
ENV APP_VERSION 1.0.0
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
HEALTHCHECK --timeout=2s CMD curl -f localhost || exit 1
Dockerfile para descompactar o node_exporte, mas lembrando que o mesmo precisa estar na máquina local para descontrair no local desejado
FROM debian:10
LABEL maintainer="[email protected]"
RUN apt-get update && apt-get install nginx curl -y && rm -rf /var/lib/apt/lists/*
EXPOSE 80
ADD node_exporter-1.6.0.linux-amd64.tar.gz /root/node-exporter
COPY index.html /var/www/html/
WORKDIR /var/www/html
ENV APP_VERSION 1.0.0
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
HEALTHCHECK --timeout=2s CMD curl -f localhost || exit 1
==============================================
Criando e gerenciando imagens
Agora eu quero criar minha imagem, posso?
Claro que pode!
E mais, vamos aprender de duas formas simples e intuitivas.
Uma das coisas mais interessantes do Docker é a possibilidade de usar imagens criadas por outras pessoas ao redor do mundo através de algum registry como o Docker Hub. Isso agiliza muito a sua vida, ainda mais quando você precisa apenas testar uma determinada tecnologia. O POC (Proof of Concept -- em português, prova de conceito) se torna muito mais ágil, fazendo com que você consiga testar diversas ferramentas no mesmo tempo em que levaria para testar somente uma sem o Docker.
Entretanto, em determinados momentos precisamos criar a nossa própria imagem do zero, ou então modificar uma imagem criada por terceiros e salvar essas alterações em uma nova imagem.
Agora vamos ver os dois casos: como montar uma distribuição praticamente do zero utilizando somente instruções através do dockerfile e outra realizando modificações em uma imagem já existente e salvando em uma imagem nova.
8.2. Vamos começar do começo então, dockerfile!
Vamos montar a nossa primeira imagem utilizando como roteiro de criação um dockerfile. Você verá o quanto é simples a criação de um dockerfile bem completo e prático. :)
Para começar, vamos criar um diretório chamado "/root/Dockerfiles".
# mkdir /root/Dockerfiles
Agora começaremos a criação do nosso dockerfile, nosso mapa de criação da imagem. Para que possamos organizá-lo melhor, vamos criar um diretório chamado "apache", onde guardaremos esse nosso primeiro exemplo:
# cd /root/Dockerfiles/
# mkdir apache
Por enquanto, vamos apenas criar um arquivo chamado "Dockerfile" e adicionar o conteúdo conforme exemplo a seguir:
# cd apache
# vim Dockerfile
FROM debian:10
RUN apt-get update && apt-get install -y apache2 && apt-get clean
ENV APACHE_LOCK_DIR="/var/lock"
ENV APACHE_PID_FILE="/var/run/apache2.pid"
ENV APACHE_RUN_USER="www-data"
ENV APACHE_RUN_GROUP="www-data"
ENV APACHE_LOG_DIR="/var/log/apache2"
LABEL description="Webserver"
VOLUME /var/www/html/
EXPOSE 80
Muito bom! Agora que você já adicionou as informações conforme o exemplo, vamos entender cada seção utilizada nesse nosso primeiro dockerfile:
FROM -- Indica a imagem a servir como base.
RUN -- Lista de comandos que deseja executar na criação da imagem.
ENV -- Define variáveis de ambiente.
LABEL -- Adiciona metadata à imagem, como descrição, versão, etc.
VOLUME -- Define um volume a ser montado no container.
Após a criação do arquivo, vamos buildar (construir a nossa imagem) da seguinte forma:
# docker build .
Lembre-se: você deverá estar no diretório onde está o seu dockerfile.
Todos os passos que definimos em nosso dockerfile serão realizados, como a instalação dos pacotes solicitados e todas as demais tarefas.
Successfully built 53de2cee9e71
Muito bem! Como podemos notar na última linha da saída do "docker build", a imagem foi criada com sucesso! :D
Vamos executar o "docker image ls" para ver se está tudo certo com a nossa primeira imagem!
root@linuxtips:~/Dockerfile/apache# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 53de2cee9e71 2 minutes ago 193.4 MB
A nossa imagem foi criada! Porém, temos um problema. :/
A imagem foi criada e está totalmente funcional, mas, quando a buildamos, não passamos o parâmetro "-t", que é o responsável por adicionar uma tag ("nome:versão") à imagem.
Vamos executar novamente o build, porém passando o parâmetro '-t', conforme o exemplo a seguir:
# docker build -t linuxtips/apache:1.0 .
Agora vamos ver se realmente a imagem foi criada, adicionando um nome e uma versão a ela:
root@linuxtips:~/Dockerfile/apache# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
linuxtips/apache 1.0 53de2cee9e71 5 minutes ago 193.4 MB
Maravilha! Funcionou conforme esperávamos!
Vamos executar um container utilizando nossa imagem como base:
# docker container run -ti linuxtips/apache:1.0
Agora já estamos no container. Vamos verificar se o Apache2 está em execução. Se ainda não estiver, vamos iniciá-lo e verificar se a porta 80 está "LISTEN".
root@70dd36fe2d3b:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 1 21:33 ? 00:00:00 /bin/bash
root 6 1 0 21:33 ? 00:00:00 ps -ef
root@70dd36fe2d3b:/# /etc/init.d/apache2 start
[....] Starting Apache httpd web server: apache2AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppress this message
. ok
root@70dd36fe2d3b:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 21:33 ? 00:00:00 /bin/bash
root 30 1 0 21:33 ? 00:00:00 /usr/sbin/apache2 -k start
www-data 33 30 0 21:33 ? 00:00:00 /usr/sbin/apache2 -k start
www-data 34 30 0 21:33 ? 00:00:00 /usr/sbin/apache2 -k start
root 109 1 0 21:33 ? 00:00:00 ps -ef
root@70dd36fe2d3b:/# ss -atn
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 :::80 :::*
root@70dd36fe2d3b:/# ip addr show eth0
50: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.4/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:4/64 scope link
valid_lft forever preferred_lft forever
root@70dd36fe2d3b:/#
No código anterior é possível observar o IP do container na saída do "ip addr". Vamos testar a comunicação com o container a partir do host.
No host, digite:
# curl <IP DO CONTAINER>
O "curl" retornou a página de boas-vindas do Apache2, ou seja, tudo está funcionando muito bem e o Apache2, respondendo conforme esperado!
Maaaaaasssss, não é interessante que eu tenha que entrar no container para subir o meu processo do Apache. Todo container deve executar seu processo em primeiro plano e esse processo deve subir de forma automática e não com um serumaninho acessando o container e subindo o serviço. Vimos antes somente como primeiro exemplo, agora vamos aperfeiçoá-lo e deixá-lo como deve estar! :D
A primeira coisa é deixar o nosso dockerfile como segue:
# vim Dockerfile
FROM debian:10
RUN apt-get update && apt-get install -y apache2 && apt-get clean
ENV APACHE_LOCK_DIR="/var/lock"
ENV APACHE_PID_FILE="/var/run/apache2/apache2.pid"
ENV APACHE_RUN_USER="www-data"
ENV APACHE_RUN_DIR="/var/run/apache2"
ENV APACHE_RUN_GROUP="www-data"
ENV APACHE_LOG_DIR="/var/log/apache2"
LABEL description="Webserver"
VOLUME /var/www/html/
EXPOSE 80
ENTRYPOINT ["/usr/sbin/apachectl"]
CMD ["-D", "FOREGROUND"]
Perceba que agora nós adicionamos mais duas opções: o ENTRYPOINT e o CMD!
Ficou curioso sobre o que eles fazem? Então 'bora aprender muito mais opções possíveis de serem adicionadas em um dockerfile!
Bora aprender um pouco mais sobre dockerfile?
Vamos agora aprender um pouco mais sobre as opções que podemos utilizar quando estamos criando um dockerfile:
ADD -- Copia novos arquivos, diretórios, arquivos TAR ou arquivos remotos e os adiciona ao filesystem do container.
CMD -- Executa um comando. Diferentemente do RUN, que executa o comando no momento em que está "buildando" a imagem, o CMD irá fazê-lo somente quando o container é iniciado.
LABEL -- Adiciona metadados à imagem, como versão, descrição e fabricante.
COPY -- Copia novos arquivos e diretórios e os adiciona ao filesystem do container.
ENTRYPOINT -- Permite que você configure um container para rodar um executável. Quando esse executável for finalizado, o container também será.
ENV -- Informa variáveis de ambiente ao container.
EXPOSE -- Informa qual porta o container estará ouvindo.
FROM -- Indica qual imagem será utilizada como base. Ela precisa ser a primeira linha do dockerfile.
MAINTAINER -- Autor da imagem.
RUN -- Executa qualquer comando em uma nova camada no topo da imagem e "commita" as alterações. Essas alterações você poderá utilizar nas próximas instruções de seu dockerfile.
USER -- Determina qual usuário será utilizado na imagem. Por default é o root.
VOLUME -- Permite a criação de um ponto de montagem no container.
WORKDIR -- Responsável por mudar do diretório "/" (raiz) para o especificado nele.
Um detalhe superimportante de mencionar é que quando estamos trabalhando com o ENTRYPOINT e o CMD dentro do mesmo dockerfile, o CMD somente aceita parâmetros do ENTRYPOINT, conforme nosso exemplo do dockerfile anterior:
ENTRYPOINT ["/usr/sbin/apachectl"]
CMD ["-D", "FOREGROUND"]
Onde:
"/usr/sbin/apachectl" -- Esse é o comando.
"-D", "FOREGROUND" -- Esse é o argumento, o parâmetro.
No shell, por exemplo, a execução ficaria assim:
# /usr/sbin/apachectl -D FOREGROUND
Ou seja, assim você está iniciando o Apache passando a instrução para que ele seja iniciado em primeiro plano, como deve ser. :D
Para maiores detalhes sobre como criar imagens, veja essa apresentação criada pelo Jeferson: https://www.slideshare.net/jfnredes/images-deep-dive.
======================================================
Técnica para usar múltiplos estágios de construção para otimizar imagens.
DockerFile MultiStage
EX para verificar o tamanho que vai ficar
Tamanho dessa imagem 1.1gb
FROM golang:1.18
COPY . ./
WORKDIR /app
RUN go build -o /app/hello
CMD ["/app/hello"]
Imagem mais compacta usando multistage
FROM golang:1.18 as buildando
WORKDIR /app
COPY . ./
RUN go build -o /app/hello
FROM alpine:3.15.9
COPY --from=buildando /app/hello /app/hello
CMD ["/app/hello"]
==============================================================
Multi-stage
Um importante e recente recurso adicionado ao dockerfile visa facilitar a vida de quem pretende criar imagens de containers de forma efetiva. Esse cara é o multi-stage!
O multi-stage nada mais é do que a possibilidade de você criar uma espécie de pipeline em nosso dockerfile, podendo inclusive ter duas entradas FROM.
Esse recurso é muito utilizado quando queremos, por exemplo, compilar a nossa aplicação em um container e executá-la, porém não queremos ter aquela quantidade enorme de pacotes instalados em nossos containers necessários sempre quando se quer compilar códigos de alguma linguagem, como C, Java ou Golang.
Vamos a um exemplo para que possamos entender melhor como isso funciona!
Para isso, preparei uma app escrita em Golang superavançada para o nosso teste:
# vim goapp.go
package main
import "fmt"
func main() {
fmt.Println("GIROPOPS STRIGUS GIRUS - LINUXTIPS")
}
Achou que seria algo avançado? Impossível, fomos nós que fizemos. :D
Bem, agora vamos criar um dockerfile para criar a nossa imagem e assim executar a nossa app.
# vim Dockerfile
FROM golang:1.18
WORKDIR /app
COPY . ./
RUN go mod init hello
RUN go build -o /app/hello
CMD ["/app/hello"]
Pronto! Agora vamos realizar o build.
# docker build -t goapp:1.0 .
Listando a nossa imagem:
# docker image ls | grep goapp
goapp 1.0 50451808b384 11 seconds ago 781MB
Agora vamos executá-la e ver a nossa fantástica app em execução:
# docker container run -ti goapp:1.0
GIROPOPS STRIGUS GIRUS -- LINUXTIPS
Pronto! Nossa app e nossa imagem estão funcionando! Sucesso!
Porém, podemos melhorar muita coisa se começarmos a utilizar o nosso poderoso recurso, o multi-stage!
Vamos refazer o nosso dockerfile utilizando o multi-stage, entender como ele funciona e a diferença entre as duas imagens.
Vamos deixar nosso dockerfile dessa maneira:
# vim Dockerfile
FROM golang:1.18 as buildando
WORKDIR /app
COPY . ./
RUN go mod init hello
RUN go build -o /app/hello
FROM alpine:3.15.9
COPY --from=buildando /app/hello /app/hello
CMD ["/app/hello"]
Perceba que agora nós temos duas entradas FROM, o que não era possível antes do multi-stage. Mas por que isso?
O que está acontecendo é que agora temos o dockerfile dividido em duas seções. Cada entrada FROM define o início de um bloco, uma etapa.
Então, em nosso primeiro bloco temos:
===================================================
FROM golang AS buildando -- Estamos utilizando a imagem do Golang para criação da imagem de container, e aqui estamos apelidando esse bloco como "buildando".
ADD . ./ -- Adicionando o código de nossa app dentro do container.
WORKDIR /app -- Definindo que o diretório de trabalho é o "/app", ou seja, quando o container iniciar, estaremos nesse diretório.
RUN go build -o /app/hello -- Vamos executar o build de nossa app Golang.
Já no segundo bloco temos o seguinte:
FROM alpine:3.15.9 -- Iniciando o segundo bloco e utilizando a imagem do Alpine para criação da imagem de container.
COPY --from=buildando /app/hello /app/hello-- Aqui está a mágica: vamos copiar do bloco chamado "buildando" um arquivo dentro de "/app/hello" para o diretório "/app" do container que estamos tratando nesse bloco, ou seja, copiamos o binário que foi compilado no bloco anterior e o trouxemos para esse.
CMD ["/app/hello"] -- Aqui vamos executar a nossa sensacional app. :)
===================================
Agora que já entendemos todas as linhas do nosso novo dockerfile, 'bora realizar o build dele.
# docker build -t goapp_multistage:1.0 .
Vamos executar a nossa imagem para ver se está tudo funcionando:
# docker container run -ti goapp_multistage:1.0
GIROPOPS STRIGUS GIRUS - LINUXTIPS
Será que existe diferença de tamanho entre elas? Vamos conferir:
# docker image ls | grep goapp
goapp_multistage 1.0 dfe57485b7f0 22 seconds ago 7.07MB
goapp 1.0 50451808b384 15 minutes ago 781MB
A diferença de tamanho é brutal, pois em nossa primeira imagem precisamos ter um monte de pacotes para que o build da app Golang ocorra. Já em nossa segunda imagem também utilizamos a imagem do Golang e todos os seus pacotes para buildar a nossa app, porém descartamos a primeira imagem e somente copiamos o binário para o segundo bloco, onde estamos utilizando a imagem do Alpine, que é superenxuta.
Ou seja, utilizamos o primeiro bloco para compilar a nossa app e o segundo bloco somente para executá-la. Simples assim, simples como voar! :D
==========================================================================
Declarando uma variavel no dockerfile usando "ENV"
FROM golang:1.18 as buildando
WORKDIR /app
COPY . ./
RUN go build -o /app/hello
FROM alpine:3.15.9
COPY --from=buildando /app/hello /app/hello
ENV app="hello_world"
CMD ["/app/hello"]
buidl passando argumentos
docker build -t go-teste:5.0 --build-arg giropops=girus .
ARG é usando no momento do buil (Define uma variável para ser usada durante a fase de construção da imagem.)
ENV transforme em uma variavel dentro do container
===========================================================================
Usando VOLUME
FROM golang:1.18 as buildando
WORKDIR /app
COPY . ./
RUN go build -o /app/hello
FROM alpine:3.15.9
COPY --from=buildando /app/hello /app/hello
ENV APP="hello_world"
ARG GIROPOPS="strigus"
ENV GIROPOP=#GIROPOPS
RUN echo "o giropops é: $GIROPOPS"
VOLUME /app/dados
CMD ["/app/hello"]
===============================================================================
Glossário de Dockerfile
ADD: Instrução utilizada no Dockerfile para copiar arquivos e diretórios para dentro do container.
CMD: Instrução utilizada no Dockerfile para especificar o comando padrão a ser executado quando o container for iniciado.
COPY: Instrução utilizada no Dockerfile para copiar arquivos e diretórios para dentro do container.
ENTRYPOINT: Instrução utilizada no Dockerfile para especificar o comando padrão a ser executado quando o container for iniciado, porém não pode ser substituído ao iniciar o container.
ENV: Instrução utilizada no Dockerfile para definir variáveis de ambiente que serão utilizadas durante a construção e execução do container.
EXPOSE: Instrução utilizada no Dockerfile para definir as portas em que o container irá escutar, permitindo a comunicação com outros containers ou com o host.
FROM: Instrução utilizada no Dockerfile para especificar a imagem base que será utilizada para construir o container.
LABEL: Instrução utilizada no Dockerfile para adicionar metadados à imagem, como informações do autor e descrição.
MAINTAINER: Instrução utilizada no Dockerfile para especificar o autor da imagem.
RUN: Instrução utilizada no Dockerfile para executar comandos durante a construção do container.
USER: Instrução utilizada no Dockerfile para especificar o usuário que será usado para executar os comandos dentro do container.
VOLUME: Instrução utilizada no Dockerfile para definir um ponto de montagem de volume, permitindo o compartilhamento de dados entre o host e o container.
WORKDIR: Instrução utilizada no Dockerfile para definir o diretório de trabalho dentro do container, onde os comandos serão executados.
Lembre-se de sempre consultar a documentação oficial do Docker para obter informações completas sobre cada termo.
==================================================================================
Utilizando o dockerhub donwload de imagem e upload de imagem
Enviando uma imagem
obi@obi-System-Product-Name:/home/pick2024/Day02/DockerFiles$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
go-teste 4.0 108c9c262e67 52 minutes ago 7.35MB
obivas/go-teste 4.0 108c9c262e67 52 minutes ago 7.35MB
go-teste 5.0 1351c4e9cdde 52 minutes ago 7.35MB
obivas/go-teste 5.0 1351c4e9cdde 52 minutes ago 7.35MB
<none> <none> 0d7acc669af4 56 minutes ago 7.35MB
<none> <none> eab7c3d72205 About an hour ago 7.35MB
<none> <none> 5c2d5125a8d8 About an hour ago 7.35MB
go-teste 2.0 c5f21c8c1cbc 24 hours ago 7.35MB
go-teste 3.0 08efd6d22283 24 hours ago 7.35MB
go-teste 1.0 4d8b23375942 24 hours ago 1.11GB
obivas5 2.0 7b3eed173900 9 days ago 169MB
obivas01 1.0 a38bc80f7268 11 days ago 169MB
ubuntu latest ca2b0f26964c 4 weeks ago 77.9MB
nginx latest 92b11f67642b 6 weeks ago 187MB
centos 7 eeb6ee3f44bd 2 years ago 204MB
obi@obi-System-Product-Name:/home/pick2024/Day02/DockerFiles$ docker push obivas/go-teste:5.0
The push refers to repository [docker.io/obivas/go-teste]
5f70bf18a086: Pushed
2129e946629c: Pushed
579bc0f2bef2: Mounted from library/alpine
5.0: digest: sha256:972ef18b918d5095bebddb9a62fa6a46471a9f644d0732493a1beda377e0cd53 size: 945
======================================================================
Timeline: Criação de uma Imagem Docker
Criação do Dockerfile: O primeiro passo na criação de uma imagem Docker é criar um arquivo chamado Dockerfile. Esse arquivo contém as instruções necessárias para construir a imagem, como a escolha da base, a instalação de dependências e a configuração do ambiente.
Build da Imagem: Após a criação do Dockerfile, é necessário executar o comando docker build para iniciar o processo de construção da imagem. Nesse momento, o Docker irá ler o arquivo Dockerfile e compilar a imagem conforme as instruções especificadas.
Tag da Imagem: Após a conclusão do build, é possível adicionar tags à imagem para facilitar sua identificação e versionamento. Por exemplo, podemos adicionar uma tag indicando a versão da aplicação ou o ambiente de destino.
Push da Imagem: Para disponibilizar a imagem em um repositório remoto, é necessário utilizar o comando docker push. Esse comando envia a imagem para um registro, como o Docker Hub ou um registro privado, permitindo que outras pessoas possam baixar e utilizar a imagem.
Verificação de Vulnerabilidades: É importante garantir a segurança da imagem antes de disponibilizá-la para uso. Para isso, podemos utilizar ferramentas de verificação de vulnerabilidades, como o Trivy. Essas ferramentas analisam a imagem em busca de componentes com falhas de segurança conhecidas.
Assinatura com o Cosign: Para adicionar uma camada extra de segurança, é possível assinar digitalmente a imagem utilizando o Cosign. Essa assinatura garante a integridade da imagem, permitindo que os usuários verifiquem a autenticidade e a procedência da mesma.
Esses são os principais marcos na criação de uma imagem Docker, desde a criação do Dockerfile até a assinatura com o Cosign. Cada passo é essencial para garantir a qualidade, segurança e confiabilidade da imagem.
========================================================================