ボリュームに単一のファイルをマウントする方法


257

PHPアプリケーションをドッキングしようとしています。dockerfileでアーカイブをダウンロードし、解凍します。

すべてが正常に動作しますが、新しいバージョンがリリースされ、dockerfileを更新した場合、config.phpが上書きされるため、アプリケーションを再インストールする必要があります。

データベースと同じように、ファイルをボリュームとしてマウントできると思いました。

ボリュームとダイレクトパスの2つの方法で試してみました。

docker-compose:

version: '2'
services:
  app:
    build: src
    ports:
      - "8080:80"
    depends_on:
      - mysql
    volumes:
      -  app-conf:/var/www/html/upload
      -  app-conf:/var/www/html/config.php
    environment:
      DB_TYPE: mysql
      DB_MANAGER: MysqlManager

  mysql:
    image: mysql:5.6
    container_name: mysql
    volumes:
      - mysqldata:/var/lib/mysql
    ports:
      - 3306:3306
    environment:
      MYSQL_ROOT_PASSWORD:
      MYSQL_DATABASE:
      MYSQL_USER:
      MYSQL_PASSWORD:

volumes:
  mysqldata:
  app-conf:

これはエラーになります:

そして、私はマウントされたボリュームとして、与えられたパスでそれを試しました。

/src/docker/myapp/upload:/var/www/html/upload
/src/docker/myapp/upload:/var/www/html/config.php

ただし、両方の方法が機能していません。マウントされたボリュームで、アップロードが作成されることがわかります。

しかし、その後失敗します

/var/www/html/config.php \\ "で\\"ディレクトリではない\\ "\" "が発生しました

私がそれを試してみると

/src/docker/myapp/upload/config.php:/var/www/html/config.php

Dockerはアップロードフォルダーを作成してから、config.phpフォルダーを作成します。ファイルではありません。

または、構成を永続化する別の方法はありますか?


私の場合は、コンテナー/ボリュームを作成する前に、空のファイルを「操作」するだけです。ファイルが存在しない場合は、ディレクトリが作成されます。
FreeSoftwareServers

回答:


312

TL; DR /通知:

マウントしようとしているファイルの代わりにディレクトリが作成されている場合は、有効絶対パスを指定できない可能性があります。これは、サイレントで紛らわしい障害モードでよくある間違いです。

ファイルボリュームはdockerでこのように行われます(絶対パスの例(env変数を使用できます)。ファイル名を指定する必要があります):

    volumes:
      - /src/docker/myapp/upload:/var/www/html/upload
      - /src/docker/myapp/upload/config.php:/var/www/html/config.php

あなたも行うことができます:

    volumes:
      - ${PWD}/upload:/var/www/html/upload
      - ${PWD}/upload/config.php:/var/www/html/config.php

/src/docker/myappフォルダからdocker-composeを起動した場合


81
先ほど言ったように、/ src / docker / myapp / upload / config.php:/var/www/html/config.phpを試した場合、Dockerはアップロードフォルダを作成してからconfig.phpフォルダを作成します。ファイルではありません。
Jakub Juszczak 2017

9
あなたの投稿では別の方法で書きました。ファイルがある場合は、ファイルとしてマウントする必要があります。
BlackStork 2017

16
これが機能するためには、絶対パスを指定する必要がありました。PWDを使用するヒントは、ここで大いに役立ちました、ありがとう!
スティーブスミス

4
私にとっては、ファイルではなくフォルダを作成していますが、そのファイルはそのパスの後半にコピーされるので、とにかくバインドを延期することはできますか?
eKelvin 2017年

18
/src/docker/myapp/upload/config.phpがホストDockerに存在しない場合は、フォルダーが作成されます...私がやっていることは、Docker runを実行する前に空のファイルを作成するスクリプトを作成しています-理想的ですコマンドライン引数を介して私のためにそれを行うようにドッカーに指示できる場合。
Cancerbero

78

私は同様の問題に苦しんでいた。イメージを再ビルドせずに必要なときにいつでも修正できるように、構成ファイルをコンテナーにインポートしようとしました。

私は以下のコマンドがマップするだろうと思ったことを意味します $(pwd)/config.py Dockerホストから/root/app/config.pyコンテナにファイルとしてれる。

docker run -v $(pwd)/config.py:/root/app/config.py my_docker_image

ただし、config.pyファイルではなく、という名前のディレクトリが常に作成されました。

手がかりを探していて、理由を見つけました(ここから

-vまたは--volumeを使用して、Dockerホストにまだ存在しないファイルまたはディレクトリをバインドマウントする場合、-vはエンドポイントを作成します。 常にディレクトリとして作成されますます。

したがって、私のDockerホストにはないため、常にディレクトリとして作成されます $(pwd)/config.py

Dockerホストでconfig.pyを作成しても、 エクスポートするのではなく、$(pwd)/config.py単に上書き/root/app/config.pyするだけです/root/app/config.py


16
にを追加touch path/to/fileしたDockerfileので、マウントしてもファイル(作成されたディレクトリではない)になります
shadi

8
の左側:は絶対パスでなければなりません。このように機能します
sdkks

これtouchが答えでした。Dockerfileでそれを行うと、ディレクトリを作成しなくてもdocker-composeボリュームマウントが正しく機能します
ctrlbrk

27

ボリューム()の代わりにマウント--mount)を使用します-v)の

詳細:https : //docs.docker.com/storage/bind-mounts/

例:

/tmp/a.txtがDockerホストに存在することを確認します

docker run -it --mount type=bind,source=/tmp/a.txt,target=/root/a.txt alpine sh

あなたSubbu、@Jakub Juszczakこれは受け入れ答えである必要があり、それはすべての質問に答える唯一の答えだし、それは私のために働いたありがとう
neokyle

2
これは実際には質問の答えにはなりません。ボリュームも機能します(問題が絶対パスにあるため)。唯一の違い--mountとは、-vボリュームのホスト部分がまだ存在していないときの動作です。リンクに従って:> -vまたは--volumeを使用して、Dockerホストにまだ存在しないファイルまたはディレクトリをバインドマウントする場合、-vはエンドポイントを作成します。常にディレクトリとして作成されます。
ゴッドファーザー

2
これをdocker-composeに変換する方法がわかりません。「少し助けて?
msanford

@msanford答えにdocker-composeの例を追加しました。
sebisnow

10

私のようなWindowsコンテナーを使用している人は、Windowsコンテナーを使用して単一のファイルをバインドまたはマウントできないことに注意してください。

次の例は、Windowsベースのコンテナーを使用すると失敗します。コンテナー内のボリュームまたはバインドマウントの宛先は、次のいずれかでなければならないためです。存在しないか空のディレクトリ。またはC:以外のドライブ。さらに、バインドマウントのソースは、ファイルではなくローカルディレクトリである必要があります

net use z: \\remotemachine\share

docker run -v z:\foo:c:\dest ...

docker run -v \\uncpath\to\directory:c:\dest ...

docker run -v c:\foo\somefile.txt:c:\dest ...

docker run -v c:\foo:c: ...

docker run -v c:\foo:c:\existing-directory-with-contents ...

見つけるのは難しいですが、そこにあります

Windowsコンテナーへのファイルのマッピングに関するGithubの問題へのリンク



7

docker-compose fileバージョン3.2以降では、単一のファイルをコンテナーにマウントできるようにする(デフォルトのタイプ「volume」の代わりに)タイプ「bind」のボリュームマウントを指定できます。docker-compose volume docsで「bind mount」を検索してくださいhttps : //docs.docker.com/compose/compose-file/#volumes

私の場合、ローカルの開発とテストのみのシークレットを含む単一の「.secrets」ファイルをアプリケーションにマウントしようとしていました。本番環境では、私のアプリケーションはこれらの秘密をAWSからフェッチします。

省略構文を使用してこのファイルをボリュームとしてマウントした場合:

volumes:
 - ./.secrets:/data/app/.secrets

Dockerは「.secrets」ディレクトリを作成します、コンテナー外のファイルにマッピングする代わりに、コンテナー内にを作成します。私のコードでは、「IsADirectoryError:[Errno 21] Is a directory: '.secrets'」のようなエラーが発生します。

代わりに長い構文を使用してこれを修正し、読み取り専用の「バインド」ボリュームマウントを使用してシークレットファイルを指定しました。

volumes:
 - type: bind
   source: ./.secrets
   target: /data/app/.secrets
   read_only: true

これで、Dockerは.secretsファイルをコンテナに正しくマウントし、ディレクトリではなくコンテナ内にファイルを作成します。他の人がこの例が役に立てば幸いです!


ありがとうございます!それが、WordPressのwp-config.phpファイルをマウント(およびディレクトリとして作成されないようにする)するために必要なソリューションでした
Jono

6

次のdocker-compose.ymlようにファイルへの相対パスを使用することもできます(Windowsホスト、Linuxコンテナでテスト済み):

 volumes:
      - ./test.conf:/fluentd/etc/test.conf

1
docker-composeバージョン1.24.1、ビルド4667896b version: '3.7'docker-compose.ymlファイルで指定されたMacでこれをテストしましたが、動作しました。
アキュメニュ

6
それでもファイルではなくディレクトリが表示されます。
chovy

0

私にとっての問題は、コンテナーにマウントしようとしたファイルに壊れたシンボリックリンクがあったことです


0

Windowsでも同じ問題が発生しました。 Docker 18.06.1-ce-win73 (19507)

Docker設定パネルから共有ドライブを削除して再度追加すると、すべてが再び機能しました。


0

Windowsでは、docker-compose.ymlで$ {PWD}環境変数が必要な場合、docker-compose.ymlファイルと同じディレクトリに.envファイルを作成してから、手動でフォルダーの場所を挿入できます。

CMD(pwd_var.bat):

echo PWD=%cd% >> .env

Powershell(pwd_var.ps1):

$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'; echo "PWD=$(get-location).path" >> .env

docker-compose .env変数を聞くためのより良い機能があります:https ://docs.docker.com/compose/reference/envvars/ 特にdocker composeがbaskslashで COMPOSE_CONVERT_WINDOWS_PATHSウィンドウパスを受け入れることを可能にするenv変数"\"

Windowsでファイルを共有する場合は、コンテナと共有する前にファイルが存在している必要があります。


PowerShellをdockerで使用することはできません。ベンダーロックインを作成し、コミュニティを傷つけます...
Matej 'Yin' Gagyi

0

多分これは誰かを助ける。

私はこの問題を抱えて、すべてを試しました。ボリュームバインディングは適切に見え、(ファイルではなく)ディレクトリをマウントしても、マウントされたディレクトリにファイル名は正しくありましたが、dirsとしてマウントされました。

共有ドライブを再度有効にしようとしたところ、ファイアウォールがアクティブであるとDockerが不平を言いました。

ファイアウォールを無効にした後、すべてが正常に機能していました。


有難うございます!あなたの投稿は、私のselinuxがenforcingに設定されており、それが私のトラブルのすべてを引き起こしていることを私に認識させました。あなたがた理由ダウン投票知ってはいけない_(ツ)_ /¯
オクタヴィアン

0

ファイルまたはディレクトリ/フォルダは、すべてソースファイルまたはディレクトリに依存してマウントできます。また、完全なパスを提供する必要があります。または、PWDを使用できるかどうかわからない場合は、簡単な作業例を示します。

この例では、作業ディレクトリにすでに存在するenv-commandsファイルをマウントしています

$ docker run  --rm -it -v ${PWD}/env-commands:/env-commands aravindgv/eosdt:1.0.5 /bin/bash -c "cat /env-commands"

-1

Windows 8.1でも同じ問題が発生します

パスの大文字と小文字の区別が原因であることが判明しました。私docker-compose upはディレクトリから呼び出し、cd /c/users/alex/コンテナ内でファイルがディレクトリに変換されました。

しかし、私がcd /c/Users/alex/(Usersを大文字にしないで)やりdocker-compose up、そこから呼び出したところ、うまくいきました。

私のシステムでは、Users dirとAlex dirの両方が大文字になっていますが、Users dirだけが重要なようです。

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