Como implanto um contêiner de docker e um contêiner de dados associado, incluindo o conteúdo?

18

Começarei admitindo que sou muito novato no Docker e posso estar abordando esse problema com o conjunto errado de suposições ... deixe-me saber se esse é o caso. Eu já vi muitas discussões sobre como o Docker é útil para implantação, mas não há exemplos de como isso é realmente feito.

Aqui está a maneira que eu pensei que iria funcionar:

  1. crie o contêiner de dados para armazenar alguns dados persistentes na máquina A
  2. crie o contêiner do aplicativo que usa volumes do contêiner de dados
  3. fazer algum trabalho, potencialmente alterando os dados no contêiner de dados
  4. parar o contêiner do aplicativo
  5. confirmar e marcar o contêiner de dados
  6. envie o contêiner de dados para um repositório (privado)
  7. puxe e execute a imagem da etapa 6 na máquina B
  8. retome de onde parou na máquina B

A etapa principal aqui é a etapa 5, que eu pensei que salvaria o estado atual (incluindo o conteúdo do sistema de arquivos). Você pode enviar esse estado para um repositório e retirá-lo de outro lugar, fornecendo um novo contêiner que é essencialmente idêntico ao original.

Mas isso não parece funcionar dessa maneira. O que eu acho é que a etapa 5 não faz o que eu acho que faz ou a etapa 7 (puxar e executar a imagem) "redefine" o contêiner para seu estado inicial.

Reuni um conjunto de três imagens e contêineres do Docker para testar isso: um contêiner de dados, um gravador que grava uma sequência aleatória em um arquivo no contêiner de dados a cada 30 s e um leitor que simplesmente echoes valoriza os dados arquivo contêiner e sai.

Contêiner de dados

Criado com

docker run \
    --name datatest_data \
    -v /datafolder \
    myrepository:5000/datatest-data:latest

Dockerfile:

FROM ubuntu:trusty

# make the data folder
#
RUN mkdir /datafolder

# write something to the data file
#
RUN echo "no data here!" > /datafolder/data.txt

# expose the data folder
#
VOLUME /datafolder

Escritor

Criado com

docker run \
    --rm \
    --name datatest_write \
    --volumes-from datatest_data \
    myrepository:5000/datatest-write:latest

Dockerfile:

FROM ubuntu:trusty

# Add script
#
ADD run.sh /usr/local/sbin/run.sh
RUN chmod 755 /usr/local/sbin/*.sh

CMD ["/usr/local/sbin/run.sh"]

run.sh

#!/bin/bash

while :
do
    sleep 30s

    NEW_STRING=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)

    echo "$NEW_STRING" >> /datafolder/data.txt

    date >> /datafolder/data.txt

    echo "wrote '$NEW_STRING' to file"
done

Este script grava uma sequência aleatória e a data / hora /datafolder/data.txtno contêiner de dados.

Leitor

Criado com

docker run \
    --rm \
    --name datatest_read \
    --volumes-from datatest_data \
    myrepository:5000/datatest-read:latest

Dockerfile:

FROM ubuntu:trusty

# Add scripts
ADD run.sh /run.sh
RUN chmod 0777 /run.sh

CMD ["/run.sh"]

run.sh:

#!/bin/bash

echo "reading..."

echo "-----"

cat /datafolder/data.txt

echo "-----"

Quando crio e executo esses contêineres, eles funcionam bem e funcionam da maneira que eu espero:

Pare e inicie na máquina de desenvolvimento:

  1. crie o contêiner de dados
  2. executar o escritor
  3. execute o leitor imediatamente, consulte a seção "sem dados aqui!" mensagem
  4. espere um pouco
  5. execute o leitor, veja a sequência aleatória
  6. pare o escritor
  7. reinicie o escritor
  8. execute o leitor, veja a mesma sequência aleatória

Mas cometer e pressionar não fazem o que eu espero:

  1. crie o contêiner de dados
  2. executar o escritor
  3. execute o leitor imediatamente, consulte a seção "sem dados aqui!" mensagem
  4. espere um pouco
  5. execute o leitor, veja a sequência aleatória
  6. pare o escritor
  7. confirmar e marcar o contêiner de dados com docker commit datatest_data myrepository:5000/datatest-data:latest
  8. enviar para o repositório
  9. excluir todos os contêineres e recriá-los

Nesse ponto, eu esperaria executar o leitor e ver a mesma sequência aleatória, já que o contêiner de dados foi confirmado, enviado ao repositório e depois recriado a partir da mesma imagem no repositório. No entanto, o que realmente vejo é o "sem dados aqui!" mensagem.

Alguém pode explicar onde estou errado aqui? Ou, como alternativa, aponte-me para um exemplo de como a implantação é feita com o Docker?

Kryten
fonte

Respostas:

22

Você entendeu errado como os volumes funcionam na janela de encaixe. Vou tentar explicar como os volumes se relacionam com os contêineres e as imagens do estivador e, espero, as diferenças entre os volumes dados e os contêineres de volume de dados .

Primeiro vamos relembrar algumas definições

Imagens do Docker

As imagens do Docker são essencialmente um sistema de arquivos da união + metadados. Você pode inspecionar o conteúdo do sistema de arquivos de união de imagens da janela de encaixe com o docker exportcomando e pode examinar os metadados de uma imagem de janela de encaixe com o comandodocker inspect comando

Volumes de dados

no guia do usuário do Docker :

Um volume de dados é um diretório especialmente designado em um ou mais contêineres que ignoram o Union File System para fornecer vários recursos úteis para dados persistentes ou compartilhados.

É importante observar aqui que um determinado volume (como o diretório ou arquivo que contém dados) é reutilizável apenas se existir pelo menos um contêiner de docker usando-o. As imagens do Docker não têm volumes, apenas os metadados que eventualmente informam onde os volumes seriam montados no sistema de arquivos da união. Os volumes de dados não fazem parte do sistema de arquivos da união de contêineres de encaixe, então onde estão? sob /var/lib/docker/volumesno host da janela de encaixe (enquanto os contêineres estão armazenados em /var/lib/docker/containers).

Contêineres de volume de dados

Esse tipo especial de contêiner não tem nada de especial. Eles são apenas contêineres parados usando um volume de dados com o único e único objetivo de ter pelo menos um contêiner usando esse volume de dados. Lembre-se, assim que o último contêiner (em execução ou parado) usando um determinado volume de dados for excluído, esse volume se tornará inacessível pela execução da janela de encaixe --volumes-from opção de .

Trabalhando com contêineres de volume de dados

Como criar um contêiner de volume de dados

A imagem usada para criar um contêiner de volume de dados não tem importância, pois esse contêiner pode permanecer parado e ainda preencher sua finalidade. Portanto, para criar um contêiner de dados nomeado datatest_datapara um volume, /datafoldervocê só precisa executar:

docker run --name datatest_data --volume /datafolder busybox true

Aqui baseestá o nome da imagem (convenientemente pequeno) e trueé um comando que fornecemos apenas para evitar que o daemon do docker se queixe de um comando ausente. De qualquer forma, depois que você tiver um contêiner parado nomeado datatest_datacom o único objetivo de permitir atingir esse volume com a --volumes-fromopção dodocker run comando

Como ler de um contêiner de volume de dados

Conheço duas maneiras de ler um volume de dados: o primeiro é através de um contêiner. Se você não puder ter um shell em um contêiner existente para acessar esse volume de dados, poderá executar um novo contêiner com o comando--volumes-from opção com o único objetivo de ler esses dados.

Por exemplo:

docker run --rm --volumes-from datatest_data busybox cat /datafolder/data.txt

A outra maneira é copiar o volume da /var/lib/docker/volumespasta. Você pode descobrir o nome do volume nessa pasta inspecionando os metadados de um dos contêineres usando o volume. Veja esta resposta para detalhes.

Trabalhando com volumes (desde o Docker 1.9.0)

Como criar um volume (desde o Docker 1.9.0)

O Docker 1.9.0 introduziu um novo comando docker volumeque permite criar volumes:

docker volume create --name hello

Como ler de um volume (desde o Docker 1.9.0)

Digamos que você criou um volume nomeado hellocom docker volume create --name hello, você pode montá-lo em um contêiner com a -vopção:

docker run -v hello:/data busybox ls /data

Sobre como confirmar e empurrar contêineres

Agora deve ficar claro que, como os volumes de dados não fazem parte de um contêiner (o sistema de arquivos da união), a confirmação de um contêiner para produzir uma nova imagem de janela de encaixe não persistirá nenhum dado que estivesse em um volume de dados.

Fazendo backups de volumes de dados

O guia do usuário da janela de encaixe possui um bom artigo sobre como fazer backups de volumes de dados .


Bom artigo referente a volumes: http://container42.com/2014/11/03/docker-indepth-volumes/

Thomasleveil
fonte
Parece que "a imagem usada para criar um contêiner de volume de dados não tem importância" não está correta. Apenas tente com uma imagem "scratch" que fornecerá "exec:" true ": arquivo executável não encontrado"
tcurdt 10/11/14
Apesar deste erro o recipiente será criado um cumprir o seu papel como um suporte de volume
Thomasleveil
11
Hum - talvez valha a pena abrir uma questão para isso então.
tcurdt
não, que o comportamento é esperado uma vez que a imagem do zero é uma imagem vazia que não pode ter o /bin/truebinário (ou qualquer outro) de qualquer maneira
Thomasleveil
11
Só uma coisa. Você disse que "assim que o último contêiner (em execução ou parado) usando um determinado volume de dados for excluído, o docker destruirá esse volume de / var / lib / docker / volumes.", Mas isso não é verdade: basta ver: docs.docker.com/userguide/dockervolumes (volumes de dados persistir mesmo se o recipiente em si é excluído é necessário especificar o. docker rm -vcomando contra o último recipiente para também eliminar um volume)
Juanra
1

Você também pode usar um contêiner de dados da janela de encaixe para implantar código

Não sei se é uma boa prática, mas faço assim:

FROM ubuntu:trusty

# make the data folder
#
RUN mkdir /data-image

# in my case, I have a 
# ADD dest.tar /data-image/
#
# but to follow your example :
# write something to the data file
RUN echo "no data here!" > /data-image/data.txt

# expose the data folder 
#
VOLUME /datafolder

ENTRYPOINT cp -r /data-image/* /datafolder/

Agora você pode enviar sua imagem e usar volumes de, etc ...

jmny
fonte
É isso que estou procurando, mas a resposta aceita menciona explicitamente que isso não pode ser feito. Vou experimentar agora.
andho
11
À segunda vista, a resposta aceita diz que os volumes (ou dados dentro dele) não serão confirmados, mas você pode adicionar os dados ao contêiner usando COPYou ADDe criando o volume usando VOLUMEno Dockerfile.
andho