Compose: Como `docker-compose up --force-recreate` sem reutilizar volumes anteriores

Criado em 2 out. 2015  ·  23Comentários  ·  Fonte: docker/compose

Com docker-compose 1.4.2 e docker 1.8.2
Você pode ver abaixo o primeiro volume e583c6a8 ... 5a93788a0 é reutilizado

 $ sudo docker-compose up -d --force-recreate
   Recreating remotetransmission_torrent_1...

 $ docker inspect remotetransmission_torrent_1 | grep volumes
   "/mnt/docker/volumes/e583c6a87437a5b4b1af50ee2693bd3e5dce574ec72d60dce1311215a93788a0/_data:/home/transmission/.config/transmission-daemon:rw",
   "/mnt/docker/volumes/cefce79850d7162f4f99541559c2dfc7315c83db717a7a5953118bd3c4b273e0/_data:/home/transmission/Downloads:rw"
   "Source": "/mnt/docker/volumes/e583c6a87437a5b4b1af50ee2693bd3e5dce574ec72d60dce1311215a93788a0/_data",
   "Source": "/mnt/docker/volumes/cefce79850d7162f4f99541559c2dfc7315c83db717a7a5953118bd3c4b273e0/_data",

 $ sudo docker-compose up -d --force-recreate
   Recreating remotetransmission_torrent_1...

 $ docker inspect remotetransmission_torrent_1 | grep volumes
   "/mnt/docker/volumes/e583c6a87437a5b4b1af50ee2693bd3e5dce574ec72d60dce1311215a93788a0/_data:/home/transmission/.config/transmission-daemon:rw",
   "/mnt/docker/volumes/cefce79850d7162f4f99541559c2dfc7315c83db717a7a5953118bd3c4b273e0/_data:/home/transmission/Downloads:rw"
   "Source": "/mnt/docker/volumes/e583c6a87437a5b4b1af50ee2693bd3e5dce574ec72d60dce1311215a93788a0/_data",
   "Source": "/mnt/docker/volumes/cefce79850d7162f4f99541559c2dfc7315c83db717a7a5953118bd3c4b273e0/_data",

Sou forçado a stop depois rm para criar alguns novos volumes

 $ sudo docker-compose stop 
   Stopping remotetransmission_torrent_1... done

 $ sudo docker-compose rm
   Going to remove remotetransmission_torrent_1
   Are you sure? [yN] y
   Removing remotetransmission_torrent_1... done

 $ sudo docker-compose up -d --force-recreate
   Creating remotetransmission_torrent_1...

 $ docker inspect remotetransmission_torrent_1 | grep volumes
   "Source": "/mnt/docker/volumes/c5bb9a8f7b68c762c42e9c0ee92afbca3aa0d7ff9d09aaf45fd260f6fc663ec9/_data",
   "Source": "/mnt/docker/volumes/9dcce8440bafc8893e07352111d1aefb625c36df10da6dc4eaa593220266ea31/_data",

_
Existe uma maneira melhor do que o método stop/rm ?

areup kindocs kinquestion

Comentários muito úteis

Esta política parece violar as práticas recomendadas do docker e nos causou _tons_ de dor de cabeça ao solucionar o problema de porque a recriação de contêineres estava vazando. Quando digo ao docker para recriar, isso não significa "persistir alguns dados nas execuções do contêiner, mas reiniciar os processos nos contêineres". Significa pavimentar a terra e começar de novo. Se eu quisesse salvar os volumes, montaria os volumes explicitamente. Eu _nunca_ espero que volumes montados automaticamente de qualquer tipo persistam nas execuções do contêiner.

Todos 23 comentários

stop/rm é o caminho certo. Os dados em volumes podem ser importantes, por isso queremos dificultar a sua remoção acidental.

Provavelmente poderíamos documentar isso um pouco melhor.

Esta política parece violar as práticas recomendadas do docker e nos causou _tons_ de dor de cabeça ao solucionar o problema de porque a recriação de contêineres estava vazando. Quando digo ao docker para recriar, isso não significa "persistir alguns dados nas execuções do contêiner, mas reiniciar os processos nos contêineres". Significa pavimentar a terra e começar de novo. Se eu quisesse salvar os volumes, montaria os volumes explicitamente. Eu _nunca_ espero que volumes montados automaticamente de qualquer tipo persistam nas execuções do contêiner.

A persistência de dados em execuções é realmente a única razão para usar volumes. Se você não deseja dados persistentes, por que os está colocando em um volume?

Não estou ajustando o volume. Meu docker-compose.yml não tem nenhum volume configurado e não estou passando nada para docker-compose.yml para anexar nenhum volume.

Comando:

docker-compose up --force-recreate --abort-on-container-exit --build foo

docker-compose.yml:

version: '2'
services:
  foo:
    build:
      context: .
      dockerfile: src/integration/foo/Dockerfile
    ports:
      - "3306:3306"
      - "33060:33060"

Dockerfile:

FROM mysql:5.7

COPY schema/foo/migration.sql /data/db_schema.sql
COPY src/integration/foo/create_test_db.sh /docker-entrypoint-initdb.d/create_test_db.sh
ENV MYSQL_ALLOW_EMPTY_PASSWORD true

EXPOSE 3306 33060

create_test_db.sh:

#!/bin/bash
set -e
mysql --no-defaults -u root -e "drop database if exists agent_state; create database foo"
mysql --no-defaults -u root foo < "/data/db_schema.sql"

Se eu executar o procedimento acima, escrevo algumas coisas no banco de dados, depois SIG_INT e, em seguida, execute o comando novamente. Os dados que coloquei no banco de dados são mantidos durante a execução.

Esse é um problema com a imagem MySQL. Cria um volume na base
imagem. Você pode contornar o problema usando um MySQL diferente
imagem ou possivelmente forçando-o a usar um caminho diferente para os dados.

Em 19 de outubro de 2016, 18:36, "Micah Zoltu" [email protected] escreveu:

Não estou ajustando o volume. Meu docker-compose.yml não tem nenhum
configuração de volumes e não estou passando nada para docker-compose.yml para
anexe quaisquer volumes.

Comando:

docker-compose up --force-recreate --abort-on-container-exit --build foo

docker-compose.yml:

versão 2'
Serviços:
foo:
Construir:
contexto:.
dockerfile: src / integration / foo / Dockerfile
portas:
- "3306: 3306"
- "33060: 33060"

Dockerfile:

DE mysql: 5,7

COPY schema / foo / migration.sql /data/db_schema.sql
COPY src / integration / foo / create_test_db.sh /docker-entrypoint-initdb.d/create_test_db.sh
ENV MYSQL_ALLOW_EMPTY_PASSWORD verdadeiro

EXPOSE 3306 33060

create_test_db.sh:

! / bin / bash

set -e
mysql --no-defaults -u root -e "descartar banco de dados se existir agent_state; criar banco de dados foo"
mysql --no-defaults -u root foo <"/data/db_schema.sql"

Se eu executar o acima, escreva algumas coisas no banco de dados, então SIG_INT, e execute o
comando novamente os dados que coloquei no banco de dados são persistentes durante a execução.

-
Você está recebendo isso porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/docker/compose/issues/2127#issuecomment -254986952,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAa_RG_pJj0i-OSCfcBlG__8ToFDtGKMks5q1sWlgaJpZM4GHruC
.

Hmm, isso viola meu entendimento sobre contêineres docker. Como é montar um volume sem que eu forneça um caminho no host? Meu entendimento é que os contêineres do docker são efêmeros, a menos que você monte explicitamente um volume.

Um volume não precisa de um caminho de host. Existem três tipos de volumes:

  • montagens de ligação de host ( -v /host:/container )
  • volumes nomeados ( -v name:/container , criado com docker volume create )
  • volumes anônimos ( -v /container , ou VOLUME dentro de um Dockerfile )

A imagem mysql usa um volume anônimo. No tempo de execução, você pode dizer ao contêiner para usar um volume diferente para aquele caminho no contêiner, mas se não fizer isso, o volume anônimo ainda estará lá.

Volumes anônimos não são bons. Eles são os mais antigos dos três e muito de seu comportamento é legado que é mantido apenas por motivos de compatibilidade com versões anteriores.

Pelo menos alguma opção de linha de comando a la "--recreate-volumes" seria bom ...

OK, pessoal, aqui está o caso para pensar:

1) Eu quero remontar meu diretório público Rails no contêiner nginx, para que algumas coisas estáticas possam ser servidas pelo nginx diretamente.
2) Eu atribuo um volume "anônimo" (não montado no host, não nomeado) para / usr / local / app / app / public e compartilho com o nginx via "volumes_from"
3) O conteúdo "público" é frequentemente alterado em compilações de imagens - não apenas arquivos de nível superior, mas alguns arquivos em subdiretórios (isso é importante)

Atualmente, se eu recriar contêineres, acabo com uma versão antiga de "público" - o conteúdo da imagem é simplesmente ignorado. Sim, o Docker deve copiar os arquivos

Portanto, sou forçado a executar a sequência "stop-rm-up" (não muito conveniente na produção) ou a usar um diretório separado como um volume compartilhado e chamar explicitamente 'rsync' no início do contêiner do aplicativo para preenchê-lo / atualizá-lo.

Se houvesse uma maneira de permitir que o volume anônimo acompanhasse o contêiner pai, seria uma grande melhoria.

Não use volumes para código (ou ativos estáticos). Os volumes são para dados que você deseja preservar entre as implantações, o que é o oposto do que você deseja aqui. Crie a imagem nginx com os ativos estáticos ou faça proxy de algum contêiner de servidor da web que os contenha.

Obrigado pelo ponto de vista! Não pensei dessa perspectiva ainda.

Parece ser um dos problemas conceituais com a arquitetura Docker (ainda em evolução). Vimos a evolução do conceito de volumes de dados até agora (por exemplo, de "contêineres de dados" para "volumes nomeados") e provavelmente ainda não foi concluído.

Se você olhar em https://docs.docker.com/engine/tutorials/dockervolumes/#/data -volumes, verá que a maioria dos benefícios descritos (ignorar AUFS, compartilhamento) não estão necessariamente ligados à persistência de dados ( para os quais os volumes foram originalmente projetados).

Portanto, não é surpresa que as pessoas (inclusive eu) estejam tentando usar os volumes de várias maneiras além de seu propósito original. Por exemplo, para compartilhar dados efêmeros ou controlados por imagem de um contêiner para outro, sem muitas cópias explícitas.

Talvez algum dia descubramos a maneira padrão consistente de fazer isso. :) Até agora, é possível usar algumas soluções alternativas bastante simples descritas acima. Não é ideal, mas é aceitável, desde que as expectativas arquitetônicas sejam definidas de maneira adequada.

Mais uma vez, obrigado pela sua resposta, esclarecimento e pelo ótimo trabalho que vem realizando!

Corri para este problema hoje, obrigado pelas ótimas explicações aqui a todos, definitivamente me ajudou a entender o problema.

Um grande ponto de confusão para mim foi entender que a tag VOLUME em um dockerfile faz com que um volume anônimo consistente seja criado. Posso ter perdido isso na documentação, mas não consegui encontrar menção a isso.

@dnephin

Conforme mencionado @ hleb-rubanau. Executar um único contêiner com Rails e Nginx é a solução? (Assim: https://docs.docker.com/engine/admin/multi-service_container/?)

Devo quebrar as práticas recomendadas ("Cada contêiner deve ter apenas uma preocupação
") apenas para ativos de servings? :(

Para os interessados, acabei com o seguinte:

1) Em minhas configurações eu sempre uso volumes montados em bind (também conhecidos como montados em host) agora. Os volumes anônimos e nomeados têm muita lógica especial / não óbvia / condicional / inconsistente / impícita para levar em consideração. Sim, é fácil entender as especificidades do ciclo de vida e gerenciamento de cada tipo, mas descobri que é mais fácil pensar sobre arquitetura quando não estou preocupado com todas essas diferenças irrelevantes. Para FS Gluster distribuído funciona bem (ainda está sendo montado na perspectiva do Docker).

2) volume partilhado é ligam-se montado um, e que não é o directório onde bens são armazenados na imagem. No início (no ponto de entrada), estou executando o rsync local, de modo que os ativos do diretório da imagem sejam copiados / rsynced para o caminho de armazenamento compartilhado montado por ligação.

Obrigado @ hleb-rubanau

De qualquer forma, não tenho certeza se algumas ferramentas de orquestração como o RancherOS suportam essas configurações de volume ou se é a maneira certa de escalar. No final, fica mais difícil implantar com docker ...

Eu prefiro usar volumes anônimos e limpar os órfãos em algum momento.

Esta é minha pilha de trilhos de produção: https://github.com/brunocascio/AR-MTB/blob/master/docker-compose.prod.yml

Isso também me causou uma _ grande_ confusão quando estava testando a imagem jenkins / jenkins e ela não estava respeitando minhas alterações nos arquivos em / usr / share / jenkins / ref porque já os tinha copiado.

Essa é uma experiência de usuário bastante inesperada - o docker compose está criando um volume "oculto" para todos os efeitos. Se você usar o docker run normal, obterá um novo volume a cada vez. É um volume oculto no sentido de que nada em docker-compose up fala sobre ele, então, a menos que você saiba em detalhes o que a imagem está fazendo, você terá que cavar.

_Muito_ devemos imprimir uma mensagem dizendo "não recriar o volume x" para que outras pessoas no futuro não tenham que perder tempo se perguntando o que está acontecendo.

Olá @dnephin ,

Eu chamo sudo rm -rf /var/lib/docker/volumes/aa_dbdatavol e agora não posso mais docker-compose up meu postgres docker-compose .

Obtendo este erro

Criação de rede "aa_default" com o driver padrão
Criando aa_postgres_1
ERROR: for postgres Não é possível criar contêiner para postgres de serviço: não existe esse arquivo ou diretório
ERRO: Foram encontrados erros ao abrir o projeto.
Resposta de erro do daemon: Não existe tal recipiente: aa_postgres_1

Como você pode ter alguma ideia para contornar isso, compartilhe. Obrigado!

https://github.com/docker/compose/issues/2127#issuecomment -347152650

Apenas recriar a pasta resolverá meu problema.
/var/lib/docker/volumes/aa_dbdatavol/_data

Muito obrigado a sua resposta funcionou perfeitamente, na primeira vez. Muchos gracias.

@dnephin disse:

A persistência de dados em execuções é realmente a única razão para usar volumes. Se você não deseja dados persistentes, por que os está colocando em um volume?

para compartilhar arquivos entre contêineres. Existe uma maneira melhor de fazer isso sem usar volumes?

O que você quer dizer com "compartilhar arquivos"?

Você espera que um contêiner grave em um arquivo e o outro contenha essas gravações? Um sistema de arquivos geralmente não é uma boa interface entre dois serviços, mas se for o caso, você pode fazer com que um dos serviços "gerencie" o sistema de arquivos gravando atualizações no volume.

Se "compartilhamento" for apenas que dois contêineres leiam alguns dos mesmos arquivos, não há necessidade de um volume. Adicione o arquivo a ambos os contêineres com COPY .

Estou usando Docker version 18.06.1-ce, build e68fc7a e posso usar o seguinte comando para recriar volumes anônimos:

docker-compose up -d --build --force-recreate --renew-anon-volumes db

Parece que a bandeira --renew-anon-volumes foi adicionada recentemente

Estou usando Docker version 18.06.1-ce, build e68fc7a e posso usar o seguinte comando para recriar volumes anônimos:

docker-compose up -d --build --force-recreate --renew-anon-volumes db

Parece que a bandeira --renew-anon-volumes foi adicionada recentemente

Obrigado por deixar essa opção.

Esta página foi útil?
0 / 5 - 0 avaliações