Executando verificação de segurança...
1

Docker trabalhando com volumes

Acessando arquivos e diretórios

Acessando e alterando arquivos em um container

Para esse cenários vamos executar nosso container de nginx

docker run --name nginx_server -d -p 8080:80 nginx

ce127fe5bf09bc15faab2e98e9cd3eb101a916af9f125c2bd102ddb946658b8e

Note que dessa vez utilizamos o parâmetro --name que serve para especificarmos o nome do nosso container:

docker ps

CONTAINER ID   IMAGE     COMMAND                  CREATED        STATUS        PORTS                                   NAMES
ce127fe5bf09   nginx     "/docker-entrypoint.…"   1 second ago   Up 1 second   0.0.0.0:8080->80/tcp, :::8080->80/tcp   nginx_server

Sendo assim, sabemos que podemos acessar uma página do nginx a partir da nossa máquina seja no navegador no endereço http://localhost:8080/ ou por meio do curl:

curl localhost:8080

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Bom, já sabemos que para executando comandos num container podemos utilizar o comando docker exec, por exemplo:

docker ps

CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                   NAMES
ce127fe5bf09   nginx     "/docker-entrypoint.…"   3 minutes ago   Up 3 minutes   0.0.0.0:8080->80/tcp, :::8080->80/tcp   nginx_server
docker exec nginx_server ls -la

total 88
drwxr-xr-x   1 root root 4096 May 31 04:56 .
drwxr-xr-x   1 root root 4096 May 31 04:56 ..
-rwxr-xr-x   1 root root    0 May 31 04:56 .dockerenv
drwxr-xr-x   2 root root 4096 May 22 00:00 bin
drwxr-xr-x   2 root root 4096 Apr  2 11:55 boot
drwxr-xr-x   5 root root  340 May 31 04:56 dev
drwxr-xr-x   1 root root 4096 May 24 22:43 docker-entrypoint.d
-rwxrwxr-x   1 root root 1616 May 24 22:43 docker-entrypoint.sh
drwxr-xr-x   1 root root 4096 May 31 04:56 etc
drwxr-xr-x   2 root root 4096 Apr  2 11:55 home
drwxr-xr-x   1 root root 4096 May 22 00:00 lib
drwxr-xr-x   2 root root 4096 May 22 00:00 lib64
drwxr-xr-x   2 root root 4096 May 22 00:00 media
drwxr-xr-x   2 root root 4096 May 22 00:00 mnt
drwxr-xr-x   2 root root 4096 May 22 00:00 opt
dr-xr-xr-x 423 root root    0 May 31 04:56 proc
drwx------   2 root root 4096 May 22 00:00 root
drwxr-xr-x   1 root root 4096 May 31 04:56 run
drwxr-xr-x   2 root root 4096 May 22 00:00 sbin
drwxr-xr-x   2 root root 4096 May 22 00:00 srv
dr-xr-xr-x  13 root root    0 May 31 04:56 sys
drwxrwxrwt   1 root root 4096 May 24 22:43 tmp
drwxr-xr-x   1 root root 4096 May 22 00:00 usr
drwxr-xr-x   1 root root 4096 May 22 00:00 var

Sendo assim vamos entrar no container acessando o seu shell

docker exec -it nginx_server bash

root@ce127fe5bf09:/#

Uma vez dentro do container (e notem como root) podemos fazer qualquer coisa.

Nesse caso vamos editar o html padrão que o nginx exibe, esse arquivo fica no diretório /usr/share/nginx/html

Então vamos navegar até esse diretório:

root@ce127fe5bf09:/# cd /usr/share/nginx/html/

root@ce127fe5bf09:/usr/share/nginx/html# pwd
/usr/share/nginx/html

root@ce127fe5bf09:/usr/share/nginx/html# ls
50x.html  index.html

root@ce127fe5bf09:/usr/share/nginx/html#

Repare que ao listar os aquivos temos 50x.html e index.html. Vamos editar esse aquivo index !

Como o container é uma imagem muito leve, então ele vem sem algumas coisas, por exemplo sem um editor de textos simples como o vim ou vi.

Sendo assim vamos instalar o vim:

Primeiramente vamos atualizar a lista de repositórios:

root@ce127fe5bf09:/usr/share/nginx/html# apt-get update

Get:1 http://deb.debian.org/debian bullseye InRelease [116 kB]
Get:2 http://deb.debian.org/debian-security bullseye-security InRelease [48.4 kB]
Get:3 http://deb.debian.org/debian bullseye-updates InRelease [44.1 kB]
Get:4 http://deb.debian.org/debian bullseye/main amd64 Packages [8183 kB]
Get:5 http://deb.debian.org/debian-security bullseye-security/main amd64 Packages [245 kB]
Get:6 http://deb.debian.org/debian bullseye-updates/main amd64 Packages [14.8 kB]
Fetched 8650 kB in 6s (1555 kB/s)
Reading package lists... Done

root@ce127fe5bf09:/usr/share/nginx/html#

Agora vamos instalar o vim

root@ce127fe5bf09:/usr/share/nginx/html# apt-get install vim

Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  libgpm2 vim-common vim-runtime xxd
Suggested packages:
  gpm ctags vim-doc vim-scripts
The following NEW packages will be installed:
  libgpm2 vim vim-common vim-runtime xxd
0 upgraded, 5 newly installed, 0 to remove and 0 not upgraded.
Need to get 8174 kB of archives.
After this operation, 36.9 MB of additional disk space will be used.
Do you want to continue? [Y/n] y

Get:1 http://deb.debian.org/debian bullseye/main amd64 xxd amd64 2:8.2.2434-3+deb11u1 [192 kB]
Get:2 http://deb.debian.org/debian bullseye/main amd64 vim-common all 2:8.2.2434-3+deb11u1 [226 kB]
Get:3 http://deb.debian.org/debian bullseye/main amd64 libgpm2 amd64 1.20.7-8 [35.6 kB]
Get:4 http://deb.debian.org/debian bullseye/main amd64 vim-runtime all 2:8.2.2434-3+deb11u1 [6226 kB]

....

update-alternatives: warning: skip creation of /usr/share/man/man1/editor.1.gz because associated file /usr/share/man/man1/vim.1.gz (of link group editor) doesn't exist
Processing triggers for libc-bin (2.31-13+deb11u6) ...

root@ce127fe5bf09:/usr/share/nginx/html#

Agora vamos editar o arquivo index.html

root@ce127fe5bf09:/usr/share/nginx/html# vim index.html

Para iniciar a edição do arquivo pressione a tecla I agora altere o arquivo, o meu ficou assim:

<!DOCTYPE html>
<html>
  <head>
    <title>Meu Servidor !</title>
    <style>
      html {
        color-scheme: light dark;
      }
      body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
      }
    </style>
  </head>
  <body>
    <h1>It Works !</h1>
  </body>
</html>

Após a edição, pressione ESC para sair do modo de edição.

Pressione :wq e dê enter.

Para saber mais sobre o editor de texto vim leia-me

Após editar o arquivo tente acessar o nginx novamente em http://localhost:8080/, seja no navegador ou no por meio de curl:

curl localhost:8080

<!DOCTYPE html>
<html>
<head>
<title>Meu Servidor !</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>It Works !</h1>
</body>
</html>

Agora vamos sair do container e remover ele:

root@ce127fe5bf09:/usr/share/nginx/html# exit
exit
docker ps

CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                   NAMES
ce127fe5bf09   nginx     "/docker-entrypoint.…"   19 minutes ago   Up 19 minutes   0.0.0.0:8080->80/tcp, :::8080->80/tcp   nginx_server
docker rm -f nginx_server

nginx_server
docker ps -a

CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

Agora vamos subir um outro nginx

docker run --name nginx_server -d -p 8080:80 nginx

812ea61d0419b830b3235705cd6a8571852a8cbddc123bce7e8bf8f2ccfbd6cc

Agora tente acessar a página do nginx http://localhost:8080/ via navegador ou curl

curl localhost:8080

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Se você tentou acessar já viu que tudo aquilo que foi feito, todas as alterações feitas foram perdidas.

Isso por que os dados de um container morrem junto com ele, porém existe uma forma de persistir esses dados.

Vamos ver como resolver esse problema no próximo artigo onde vamos trabalhar com volumes.

Trabalhando com volumes

Crie um diretório no seu computador, vamos chamar esse diretório de html

mkdir html

Entre nesse diretório e crie o arquivo index.html

cd html

touch index.html

Vamos colocar algum conteúdo nesse arquivo, pra evitar o uso do vim vamos simplesmente usar o echo

echo "<h1>It Works</h1>" >>  index.html

cat index.html

<h1>It Works</h1>

A ideia é que possamos mapear esse diretório html para o nosso container, sendo assim vamos executar o seguinte:

Vamos remover qualquer container que esteja em execução

docker rm -f $(docker ps -qa)

812ea61d0419
docker ps -a

CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

Agora vamos subir novamente o nginx, porém dessa vez indicando pra ele um mapeamento de diretório com o parâmetro -v de volume.

docker run --name nginx_server -d -p 8080:80 -v ~/html:/usr/share/nginx/html nginx

Veja que estou apontando o diretório /html que está na minha home /home/seujorge/html e fazendo com que esse diretório esteja mapeado dentro do container no caminho /usr/share/nginx/html.

Assim sendo quando eu acessar o nginx http://localhost:8080/ o html que vai ser exibido vai ser do arquivo index.html que criamos anteriormente.

curl localhost:8080

<h1>It Works</h1>

O mais legal é que se eu alterar esse arquivo na minha máquina local, imediatamente as alterações são refletidas no nginx.

A opção -v é capaz de criar diretório e arquivos, veja o seguinte:

Vamos remover os containers

docker rm -f $(docker ps -qa)

Agora certifique-se de que você está no diretório que contem o diretório html criado anteriormente

No meu caso eu crieei em ~/html.

E vamos executar um container nginx

docker run --name nginx_server -d -p 8080:80 -v "$(pwd)"/html/x:/usr/share/nginx/html nginx

Veja que passamos na opção -v um diretório que não existia, porem se examinarmos o diretório html, vemos que o docker foi capaz de criar esse diretório x.

ls ~/html

-rw-rw-r--⠀Jorge Rabello⠀seujorge⠀61  ⠀May 31 02:37:34⠀⠀index.html
drwxr-xr-x⠀root         ⠀root    ⠀4096⠀May 31 02:46:57⠀⠀x/

Vamos remover nosso container

docker rm -f $(docker ps -qa)

8bde243dc020

E recria-lo, porém agora no lugar da opção -v vamos utilizar a opção -bind

docker run --name nginx_server -d -p 8080:80 --mount type=bind,source="$(pwd)"/html/x,target=/usr/share/nginx/html nginx

docker: Error response from daemon: invalid mount config for type "bind": bind source path does not exist: /home/seujorge/html/html/x.
See 'docker run --help'.

Veja que o docker reclama que o bind source path ou seja o caminho do source, no caso $(pwd)"/html/x não existe e o --mount é incapaz de criar.

Sendo assim, em se tratando de volumes em containers docker, há uma diferença entre utilizar -v e --mount, pois a segunda não é capaz de criar diretórios.

Até o momento trabalhamos com um tipo de volume chmado bind mount, onde podemos acessar documentos e diretórios mapeados entre a nossa máquina e o container. Apesar de ser uma forma de persistir dados, não é a única.

O docker conta com um sistema que chamamos de sistema de volumes, os volumes podem ser criados especificamente no docker.

Para acessar os volumes do docker podemos utilizar o comando docker volume, por exemplo:

docker volume ls
DRIVER    VOLUME NAME

Podemos criar um volume manualmente da seguinte forma:

docker volume create meuvolume

meuvolume
 docker volume ls

DRIVER    VOLUME NAME
local     meuvolume

Para saber mais detalhes sobre um volume podemos executar docker volume inspect

docker volume inspect meuvolume

[
    {
        "CreatedAt": "2023-05-31T02:58:01-03:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/meuvolume/_data",
        "Name": "meuvolume",
        "Options": null,
        "Scope": "local"
    }
]

Agora vamos criar um container utilizando o nosso volume:

docker run --name nginx_server -d -p 8080:80 --mount type=volume,source=meuvolume,target=/app nginx
docker ps

CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS        PORTS                                   NAMES
481e6187fe52   nginx     "/docker-entrypoint.…"   2 seconds ago   Up 1 second   0.0.0.0:8080->80/tcp, :::8080->80/tcp   nginx_server

Veja que se você acessar o container, agora você vai ver um diretório novo chamado /app que está sendo utilizado como volume.

docker exec -it nginx_server bash

root@481e6187fe52:/# ls
app  boot  docker-entrypoint.d	 etc   lib    media  opt   root  sbin  sys  usr
bin  dev   docker-entrypoint.sh  home  lib64  mnt    proc  run	 srv   tmp  var

root@481e6187fe52:/#

Vamos então criar um arquivo nesse diretório app

root@481e6187fe52:/# ls
app  boot  docker-entrypoint.d	 etc   lib    media  opt   root  sbin  sys  usr
bin  dev   docker-entrypoint.sh  home  lib64  mnt    proc  run	 srv   tmp  var

root@481e6187fe52:/# ls app/

root@481e6187fe52:/# touch app/oi.txt

root@481e6187fe52:/# ls app/
oi.txt

root@481e6187fe52:/#

Agora vamos sair do nosso container e criar um novo nginx

root@481e6187fe52:/# exit

exit
docker run --name segundo_nginx_server -d -p 8081:80 --mount type=volume,source=meuvolume,target=/app nginx

791660073bf619afb5e2611aea6a74188965b8015f0cd947719e9952d729155e

Note que eu mudei a porta para 8081 e o nome do container para segundo_nginx_server.

docker ps

CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                   NAMES
791660073bf6   nginx     "/docker-entrypoint.…"   2 seconds ago   Up 1 second    0.0.0.0:8081->80/tcp, :::8081->80/tcp   segundo_nginx_server
481e6187fe52   nginx     "/docker-entrypoint.…"   5 minutes ago   Up 5 minutes   0.0.0.0:8080->80/tcp, :::8080->80/tcp   nginx_server

Vamos executar um bash no segundo nginx

docker exec -it segundo_nginx_server bash

root@791660073bf6:/# ls app/
oi.txt

root@791660073bf6:/#

Note que ao listar os arquivos em /app vemos o arquivo oi.txt. Mesmo estando em containers diferentes o volume continua sendo o mesmo.

Então estamos compartilhando o volume entre os nossos containers.

Ou seja as alterações no volume se refletem para ambos os containers.

Uma outra forma de acessar ou referenciar volumes é utilizando o opção -v e o nome do volume, observe:

docker run --name terceiro_nginx_server -d -p 8082:80 -v meuvolume:/app nginx

069f44f11069513f31fb8b4a108d23dafecff71df464aab41ca081da96f75c41

Veja que agora temos três containers compartilhando o mesmo volume

docker ps

CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                   NAMES
069f44f11069   nginx     "/docker-entrypoint.…"   5 seconds ago    Up 4 seconds    0.0.0.0:8082->80/tcp, :::8082->80/tcp   terceiro_nginx_server
791660073bf6   nginx     "/docker-entrypoint.…"   4 minutes ago    Up 4 minutes    0.0.0.0:8081->80/tcp, :::8081->80/tcp   segundo_nginx_server
481e6187fe52   nginx     "/docker-entrypoint.…"   10 minutes ago   Up 10 minutes   0.0.0.0:8080->80/tcp, :::8080->80/tcp   nginx_server

Note que mesmo no terceiro container temos o diretório app.

docker exec -it terceiro_nginx_server bash

root@069f44f11069:/# ls app/
oi.txt

root@069f44f11069:/#

Por fim podemos excluir os container

docker rm -f $(docker ps -qa)
069f44f11069
791660073bf6
481e6187fe52

E para os volumes podemos utilizar o comando docker volume prune para limpar os dados não utilizados em volumes

docker volume prune 

WARNING! This will remove anonymous local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B

Ou simplesmente remover o volume com o comando docker volume rm

docker volume ls

DRIVER    VOLUME NAME
local     meuvolume
docker volume rm meuvolume 

meuvolume
docker volume ls

DRIVER    VOLUME NAME
Carregando publicação patrocinada...