コンテナが終了するとデータが失われる


394

Dockerのインタラクティブチュートリアルとよくある質問にもかかわらず、コンテナーが終了するとデータが失われます。

ここに記載されているようにDockerをインストールしました:http : //docs.docker.io/en/latest/installation/ubuntulinux ubuntu 13.04では問題なく。

ただし、終了するとすべてのデータが失われます。

iman@test:~$ sudo docker version
Client version: 0.6.4 
Go version (client): go1.1.2 
Git commit (client): 2f74b1c 
Server version: 0.6.4 
Git commit (server): 2f74b1c 
Go version (server): go1.1.2 
Last stable version: 0.6.4 


iman@test:~$ sudo docker run ubuntu ping
2013/10/25 08:05:47 Unable to locate ping 
iman@test:~$ sudo docker run ubuntu apt-get install ping
Reading package lists... 
Building dependency tree... 
The following NEW packages will be installed: 
  iputils-ping 
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. 
Need to get 56.1 kB of archives. 
After this operation, 143 kB of additional disk space will be used. 
Get:1 http://archive.ubuntu.com/ubuntu/ precise/main iputils-ping amd64 3:20101006-1ubuntu1 [56.1 kB] 
debconf: delaying package configuration, since apt-utils is not installed 
Fetched 56.1 kB in 0s (195 kB/s) 
Selecting previously unselected package iputils-ping. 
(Reading database ... 7545 files and directories currently installed.) 
Unpacking iputils-ping (from .../iputils-ping_3%3a20101006-1ubuntu1_amd64.deb) ... 
Setting up iputils-ping (3:20101006-1ubuntu1) ... 
iman@test:~$ sudo docker run ubuntu ping
2013/10/25 08:06:11 Unable to locate ping 
iman@test:~$ sudo docker run ubuntu touch /home/test
iman@test:~$ sudo docker run ubuntu ls /home/test
ls: cannot access /home/test: No such file or directory 

また、インタラクティブセッションでテストしたところ、同じ結果が得られました。何か忘れましたか?

編集:新しいドッカーのユーザーにとって重要

@ mohammed-noureldinや他の人が言ったように、実際にはこれは存在するコンテナではありません。常に新しいコンテナを作成するだけです。


10
これは「コンテナ終了」とは言えません。単に新しいコンテナを作成しているだけで、終了単語を使用すると多くの混乱を招く可能性があります(それが原因で私も混乱しました)。
Mohammed Noureldin 16

1
@MohammedNoureldin、あなたは正しい、終了は正しくありませんが、これはまさにあなた、私、そして他の人々が考えたことです。ですから、これは問題のある単語です。あなたの編集が質問を答えにします!新しい検索者はここでは見つかりません!
iman

私はDockerの最初の段階で、実際にはあなたの質問のために、アドレスが間違っていることに気づきました。新しいタイトルがレビューされて承認されましたが、なぜ誰かが間違ったタイトルを主張すべきなのか、それはあなたの質問であり、あなたの決断です。
Mohammed Noureldin 2016

3
@MohammedNoureldinに同意します。特定のタイトル、例、承認された回答の組み合わせは、将来の読者、特に初心者が理解するのに役立ちませんDocker。初心者は間違いなくこのようなものを探すので、タイトルと元の質問はそのままにしておくことをお勧めします。しかし、あなたが投稿を書いたときのあなたの誤解を説明する何かを追加してみませんか。それは物事を明確にするのに役立ちます。これがSOの私たちの文化です...そうではありませんか?:-)
tgogos 2017年

2
私はこの問題を抱えていました... u終了するたびにコンテナーを起動する必要があります...コンテナーを実行しないでください...新しいコンテナーを作成するこれはdocker start <container id>
docker

回答:


399

コンテナに加えた変更をコミットして実行する必要があります。これを試して:

sudo docker pull ubuntu

sudo docker run ubuntu apt-get install -y ping

次に、次のコマンドを使用してコンテナIDを取得します。

sudo docker ps -l

コンテナへの変更をコミットします。

sudo docker commit <container_id> iman/ping 

次に、コンテナを実行します。

sudo docker run iman/ping ping www.google.com

これはうまくいくはずです。


9
したがって、データを保持するために、実行ごとにコミットを使用する必要があります。
iman 2013年

5
コミットは、コンテナーに変更を加えた場合(新しいツールやデータのインストールなど)にのみ変更を保存し、次にそのイメージから新しいコンテナーを実行するときに、最後に保存した時点から開始するか、コミットして、データを保存します。
Unferth 2013年

7
@Unferth変更をコミットし続けたい場合はどうなりますか?これまでのところ、でより多くの画像を作成しています<none>。既存のイメージの上にコミットを追加し続けるにはどうすればよいですか?
Marconi

62
変更を段階的にコミットすることは、「Dockerの方法」ではありません。DOCKERFILEを使用します。
user2105103 2015年

23
コンテナ内からどのようにコミットしますか?次のシナリオを考えてみます。1)次のようにコンテナーを実行しています:docker run -i -t myimage / bin / bash 2)変更を加えます3)コンテナー内からコミットできないため、コンテナーを終了すると、以前の変更をコミットする機会がなくても、すべてのデータが
失われ

374

を使用docker runしてコンテナを開始すると、実際には、指定したイメージに基づいて新しいコンテナ作成されます。

ここでの他の有用な回答に加えて、既存のコンテナーが終了した後も変更を再開できることに注意してください。

docker start f357e2faab77 # restart it in the background
docker attach f357e2faab77 # reattach the terminal & stdin

88
docker ps実行中のDockerコンテナーのみを示します。 docker ps -a終了したものも表示され、実行を継続できます。将来の使用のためにそこでスナップショットを作成したい場合、コミットは各実行後にのみ必要です。そうしないと、コンテナー自体が引き続き使用できるようになります。
user1278519 14

2
質問してくださいjenkins。サーバーDockerをダウンロードしてCIホストで実行すると、ジョブの一部が実行され、その結果、Jenkinsサーバーがいくつかのログをディスクに書き込みます。私のサーバー(私のDockerをホストしていた)が再起動され、jenkins Dockerを再起動した場合、すべてのログファイルが失われたことになりますか?もしそうなら、jenkins例えば私はおそらくどのようにdockerを使用してCIへのjenkinsインストールを容易にすることができますか?
Jas 2015

2
@Jas同じコンテナに固執し、新しいコンテナを作成しない場合、問題はありません。最近のDockerには再起動ポリシーがあるため、マシンの再起動時に同じコンテナを再起動するように構成できます。また、外部からバックアップにアクセスできるように、jenkinsをボリュームに入れることをお勧めします。
ZeissS、2015

7
ここでは、終了後にコンテナのファイルをコピーするための便利な方法があります:docker cp $(docker ps -alq):/path/to/file .
ジョシュHabdas

3
名前でコンテナを起動してアタッチすることもできます。(例 docker run -it --name my_debian debian以降docker start my_debian && docker attach my_debian
ジョニーウィラー2017年

128

コンテナーデータを永続化するには、次の方法があります。

  1. Dockerボリューム

  2. Dockerコミット

    a)ubuntuイメージからコンテナーを作成し、bashターミナルを実行します。

       $ docker run -i -t ubuntu:14.04 /bin/bash
    

    b)ターミナルインストールカールの内側

       # apt-get update
       # apt-get install curl
    

    c)コンテナターミナルを出る

       # exit
    

    d)次のコマンドを実行して、コンテナIDをメモします。

       $ docker ps -a
    

    e)コンテナーを新しいイメージとして保存する

       $ docker commit <container_id> new_image_name:tag_name(optional)
    

    f)curlがインストールされた新しいイメージが表示されることを確認します。

       $ docker images           
    
       $ docker run -it new_image_name:tag_name bash
          # which curl
            /usr/bin/curl
    

exit以前に必要docker commitですか?ありがとう。
Abhishek Anand

2
@AbhishekAnandはい、docker runコマンドを使用してコンテナでbashを実行し-i-tオプション(TTYと対話型)があるため、コンテナ内にとどまります。ただし、Dockerはマシンのコンテナー外で実行されるため、コンテナーに内側から必要な変更を加えた後、システムのシェルに戻るにexitは、コンテナーのシェル(またはCtrl + D)を実行する必要があります。また、回答の#$にも注意してください。これらは、コマンドが書き込まれるさまざまなシェルを示しています。
エリック

簡単な質問:コミットしないと、データを失ってしまいました。それは明らかだ。しかし、nginx設定を変更すると、なぜ更新されたままになるのですか?(コミットする必要はありません)@Erik
grep

@grep明確で再現性のあるMWEがある場合は、この特定のユースケースについてまだ1つもない場合は、それについて新しい質問をしてください。
エリック

3.にdocker stop続くdocker start
carillonator

59

Unferthの回答に加えて、Dockerfileを作成することをお勧めします。

空のディレクトリに、次の内容で「Dockerfile」というファイルを作成します

FROM ubuntu
RUN apt-get install ping
ENTRYPOINT ["ping"]

Dockerfileを使用してイメージを作成します。16進数の画像番号を覚えておく必要がないようにタグを使用しましょう。

$ docker build -t iman/ping .

そして、コンテナーでイメージ実行します

$ docker run iman/ping stackoverflow.com

1
手動で2回以上行う必要がないことが、Dockerのポイントです。dockerfileを作成し、結果のイメージをコミットしてアップロードします。上記の画像を先に引き出します。
Brandon Bertelsen、2018年

11

私はあなたの質問に対してはるかに簡単な答えを得ました、次の2つのコマンドを実行してください

sudo docker run -t -d ubuntu --name mycontainername /bin/bash
sudo docker ps -a

上記のps -aコマンドは、すべてのコンテナーのリストを返します。イメージ名を参照するコンテナの名前-'ubuntu'を取ります。docker autoは、たとえば'lightlyxuyzx'--nameオプションを使用しない場合など、コンテナの名前を生成します。

-tおよび-dオプションは重要です。作成されたコンテナーは切り離され、-tオプションを使用して以下のように再接続できます。

--nameオプションを使用すると、私の場合 'mycontainername'でコンテナーに名前を付けることができます。

sudo docker exec -ti mycontainername bash

上記のコマンドは、bashシェルを使用してコンテナーにログインするのに役立ちます。この時点から、コンテナーで行った変更はすべてdockerによって自動的に保存されます。例- apt-get install curlコンテナーの内部コンテナーを問題なく終了できます。Dockerは変更を自動保存します。

次の使用方法では、このコンテナを操作するたびにこれら2つのコマンドを実行するだけです。

以下のコマンドは、停止したコンテナを開始します。

sudo docker start mycontainername

sudo docker exec -ti mycontainername bash

以下に示すポートと共有スペースの別の例:

docker run -t -d --name mycontainername -p 5000:5000 -v ~/PROJECTS/SPACE:/PROJECTSPACE 7efe2989e877 /bin/bash

私の場合:7efe2989e877-私が使用して取得した実行中の以前のコンテナのimageid

docker ps -a


4
Ubuntu 18.04上のDocker 18.09.2では、そのままでは機能しません。次の--nameように、イメージ名の前にandオプションを付けると機能します。docker run --name mycontainername -t -d ubuntu /bin/bash
StéphaneGourichon


3

私の提案は、Docker Composeを使用して、Dockerを管理することです。プロジェクトのすべてのDockerコンテナーを管理するのは簡単な方法です。バージョンをマップし、さまざまなコンテナーをリンクして連携させることができます。

ドキュメントは非常に理解しやすく、Dockerのドキュメントよりも優れています。

Docker-Composeドキュメント

ベスト


3

質問に対する上記の本当に素晴らしい答えがあります。別の答えは必要ないかもしれませんが、それでも私はこのトピックについて可能な限り簡単な言葉で個人的な意見を述べたいと思います。

以下は、結論に役立つコンテナーとイメージに関するいくつかのポイントです。

  • Dockerイメージには次のものがあります
    1. created-from-a-given-container
    2. 削除された
    3. 任意の数のコンテナーを作成するために使用
  • Dockerコンテナには次のものがあります
    1. イメージから作成
    2. 始めた
    3. 停止
    4. 再開した
    5. 削除された
    6. 任意の数の画像の作成に使用
  • docker runコマンドはこれを行います:
    1. 画像をダウンロードするか、キャッシュされた画像を使用します
    2. それから新しいコンテナを作成します
    3. コンテナを起動します
  • Dockerfileを使用してイメージを作成する場合
    1. イメージが最終的にDockerコンテナーの実行に使用されることはすでによく知られています。
    2. docker buildコマンドを発行した後、docker behind-the-scenesはbase-file-systemで実行中のコンテナーを作成し、Dockerfile内の手順に従って、開発者の必要に応じてそのコンテナーを構成します。
    3. Dockerfileの仕様を使用してコンテナーを構成すると、コンテナーはイメージとしてコミットされます。
    4. 画像がロックンロールする準備ができました!

結論

ご覧のように、DockerコンテナはDockerイメージから独立しています。

コンテナーは、そのコンテナーの一意のID [docker ps --all IDの取得に使用]を指定して再起動できます。

新しいディレクトリの作成、ファイルの作成、ツールのインストールなどの操作は、コンテナの実行中にコンテナ内で実行できます。コンテナが停止すると、すべての変更が保持されます。コンテナーの停止と再起動は、コンピューターシステムの再起動に似ています。

既に作成されたコンテナーは常に再起動に使用できますが、docker runコマンドを発行すると、イメージから新しいコンテナーが作成されるため、新しいコンピューターシステムのようになります。古いコンテナの内部で行われた変更-現在理解できるように-は、この新しいコンテナでは利用できません。

最後のメモ

データが失われたように見える理由は今では明らかだと思いますが、データは常にそこにあります。しかし、別の[古い]コンテナーにあります。したがって、docker startdocker runコマンドの違いをよくメモして、混乱しないでください。


1

同様の問題(そしてDockerfileだけではそれを修正する方法がなかった)が私をこのページに導きました。

ステージ0: すべての場合、Dockerfileで修正できることを願っています:--dnsおよび--dns-searchがDockerfileサポートに表示されるまで-イントラネットベースのリソースを統合する方法はありません。

ステージ1: Dockerfileを使用してイメージをビルドした後(深刻な問題ですが、Dockerfileは現在のフォルダーにある必要があります)、Docker runスクリプトを実行して、イントラネットベースのものを展開するイメージを用意します。例: docker run -d \ --dns=${DNSLOCAL} \ --dns=${DNSGLOBAL} \ --dns-search=intranet \ -t pack/bsp \ --name packbsp-cont \ bash -c " \ wget -r --no-parent http://intranet/intranet-content.tar.gz \ tar -xvf intranet-content.tar.gz \ sudo -u ${USERNAME} bash --norc"

ステージ2:デーモンモード でdocker runスクリプトを適用し、ローカルのDNSレコードを提供して、ローカルのものをダウンロードしてデプロイする機能を提供します

重要な点:実行スクリプトは/usr/bin/sudo -u ${USERNAME} bash --norc、インストールスクリプトが終了した後でもコンテナーを実行し続けるようなもので終わる必要があります。

いいえCTRL-p CTRL-qが押されるまで内部のコマンドプロンプト内にとどまるので、完全な自動化問題のためにインタラクティブモードでコンテナーを実行することはできません。

いいえ、対話型のbashがインストールスクリプトの最後に実行されない場合、コンテナはスクリプトの実行が終了した直後に終了し、すべてのインストール結果が失われます。

ステージ3: コンテナーはまだバックグラウンドで実行中ですが、コンテナーがインストール手順をまだ終了しているかどうかは不明です。次のブロックを使用して実行手順が終了した while ! docker container top ${CONTNAME} | grep "00[[:space:]]\{12\}bash \--norc" - do echo "." sleep 5 done ことを確認します。スクリプトは、インストールが完了した後にのみ続行されます。そして、これが呼び出す適切な瞬間です:commit、現在のコンテナーIDと宛先イメージ名を提供します(これは、ビルド/実行手順の場合と同じかもしれませんが、ローカルインストール目的のタグが付加されています。例:docker commit containerID pack/bsp:toolchained。このリンクを参照してください適切なcontainerIDを取得する方法

ステージ4:コンテナーはローカルインストールで更新され、新しく割り当てられたイメージ(目的タグが追加されたイメージ)にコミットされました。コンテナの実行を停止しても安全です。例:docker stop packbsp-cont

stage5:ローカルインストールのコンテナーを実行する必要があるときはいつでも、以前に保存したイメージでコンテナーを開始します。例:docker run -d -t pack/bsp:toolchained


1

ここで素晴らしい答え ユーザーkgsから出たドッカーを続行する方法

docker start $(docker ps -a -q --filter "status=exited")
(or in this case just docker start $(docker ps -ql) 'cos you don't want to start all of them)

docker exec -it <container-id> /bin/bash

その2行目は重要です。したがって、実行の代わりにexecが使用されます。イメージではなく、containeridで使用されます。そして、あなたはコンテナが開始された後にそれを行います。


0

この設計上の選択のポイントに対処する回答はありません。私はドッカーがこれらの2つのエラーを防ぐためにこのように機能すると思います:

  • 繰り返し再起動
  • 部分的なエラー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.