web-dev-qa-db-ja.com

node_modulesのdocker-composeボリュームが空です

私はDockerを初めて使用し、コンピューターのnode_modulesフォルダーをマップしたいと思っていました(デバッグ目的で)。

これは私のdocker-compose.ymlです

web:
  build: .
  ports:
    - "3000:3000"
  links:
    - db
  environment:
    PORT: 3000
  volumes:
    - .:/usr/src/app
    - /usr/src/app/node_modules
db:
  image: mongo:3.3
  ports:
    - "27017:27017"
  command: "--smallfiles --logpath=/dev/null"

私はDocker for Macを使用しています。実行するとdocker-compose up -dすべて正常に動作しますが、コンピューター上にnode_modulesフォルダーが作成されますが、空です。私は自分のコンテナとlsnode_modulesのbashに入り、すべてのパッケージがそこにありました。

コンピューターのコンテナーのコンテンツを取得するにはどうすればよいですか?

ありがとうございました

12
Mike Boutin

TL; DR作業例、クローンを作成して試してください:https://github.com/xbx/base-server


最初に(コンテナーを実行する前に)デバッグするために、コンピューター(画像の外側)にnode_modulesが必要です。

Node_modulesのみをデバッグする場合:

volumes:
    - /path/to/node_modules:/usr/src/app/node_modules

コードとnode_modulesの両方をデバッグする場合:

volumes:
    - .:/usr/src/app/

コンテナの外で少なくとも1回はnpm installを実行する必要があることに注意してください(またはdocker buildが生成するnpm_modulesをコピーします)。詳細が必要な場合は、今すぐお知らせください。


編集。したがって、OSXでnpmを使用しなくても、次のことができます。

  1. docker build、次にdocker cp <container-id>:/path/to/node-modules ./local-node-modules/。次に、docker-compose.ymlでそれらのファイルをマウントし、必要に応じてトラブルシューティングを行います。
  2. または、docker buildとそこ(Dockerfile)が別のディレクトリでnpm installを実行します。次に、コマンド(CMDまたはdocker-composeコマンド)で正しいディレクトリにコピー(cp)を実行しますが、このディレクトリはコンピューター(docker-compose.ymlのボリューム)から空にマウントされてから、あなたが望むものは何でもトラブルショット。

編集2.(オプション2)作業例、クローンを作成して試してください:https://github.com/xbx/base-server 私はあなたからフォークしたこのレポですべて自動的にそれを行いました。

Dockerfile

FROM node:6.3

# Install app dependencies
RUN mkdir /build-dir
WORKDIR /build-dir
COPY package.json /build-dir
RUN npm install -g babel babel-runtime babel-register mocha nodemon
RUN npm install

# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
RUN ln -s /build-dir/node_modules node_modules

# Bundle app source
COPY . /usr/src/app

EXPOSE 1234
CMD [ "npm", "start" ]

docker-compose.yml

web:
  build: .
  ports:
    - "1234:1234"
  links:
    - db # liaison avec la DB
  environment:
    PORT: 1234
  command: /command.sh
  volumes:
    - ./src/:/usr/src/app/src/
    - ./node_modules:/usr/src/app/node_modules
    - ./command.sh:/command.sh
db:
  image: mongo:3.3
  ports:
    - "27017:27017"
  command: "--smallfiles --logpath=/dev/null"

command.sh

#!/bin/bash

cp -r /build-dir/node_modules/ /usr/src/app/

exec npm start

リポジトリのクローンを作成して、docker-compose upを実行してください。それはあなたが望むことをします。 PS:同じことをより良い方法で行うように改善することができます(つまり、ベストプラクティスなど)。

私はOSXにいます、そしてそれは私のために働きます。

12
Robert

まず、操作の順序があります。イメージをビルドするとき、ボリュームはマウントされません。コンテナーを実行したときにのみマウントされます。したがって、ビルドが終了すると、すべての変更はイメージ内にのみ存在し、ボリュームには存在しません。ボリュームをディレクトリにマウントすると、その場所のイメージからのものがすべてオーバーレイされ、それらのコンテンツが表示されなくなります(1つの初期化の例外を除き、以下を参照)。


次はボリューム構文です:

  volumes:
    - .:/usr/src/app
    - /usr/src/app/node_modules

docker-composeに、現在のディレクトリからコンテナ内の/usr/src/appにホストボリュームを作成し、次に/usr/src/app/node_modulesをdockerが管理する匿名ボリュームにマップするように指示します。後者は、比較的役に立たない長いuuid文字列を含むdocker volume lsのボリュームとして表示されます。

/usr/src/app/node_modulesをホスト上のフォルダーにマップするには、上の行のように、その前にフォルダー名とコロンを含める必要があります。例えば。 /Host/dir/node_modules:/usr/src/app/node_modules

名前付きボリュームは、Dockerがdocker volume lsに表示される名前でそれらを維持するという点でホストボリュームとは少し異なります。これらのボリュームは、パスではなく名前だけで参照します。したがって、node_modules:/usr/src/app/node_modulesnode_modulesというボリュームを作成し、その名前だけでコンテナにマウントできます。

名前付きボリュームには、ホストボリュームの落とし穴になる機能が付属しているため、ここで説明しました。 Dockerは、その場所にあるイメージのコンテンツでボリュームを初期化することにより、名前付きボリュームを支援します。したがって、上記の例では、名前付きボリュームnode_modulesが空(または新規)の場合、最初に/ usr/src/app/node_modules`にあるイメージの内容をこのボリュームにコピーしてから、ボリューム内にマウントしますコンテナ。

ホストボリュームでは、その場所にあるものは何でも(空のディレクトリであっても)コンテナーに表示されるすべてが初期化されることはありません。そのディレクトリの場所にあるイメージからコンテンツを取得して、最初にその場所のホストボリュームにコピーする方法はありません。これは、コンテナ内で必要なディレクトリ権限が自動的に継承されないことも意味します。コンテナ内で機能するホストディレクトリの権限を手動で設定する必要があります。


最後に、WindowsとMac用のDockerを備えた小さな落とし穴があり、それらはVM内で実行され、ホストボリュームがVMにマウントされます。ボリュームをホストにマウントするには、ホストのフォルダーをVMと共有するようにアプリケーションを構成してから、VMのボリュームをコンテナーにマウントします。デフォルトでは、 Macでは、/ Usersフォルダーが含まれていますが、/ Projectsディレクトリや小文字の/ users(unixとbsdは大文字と小文字が区別されます)などの他のディレクトリを使用すると、Macの内容は内部に表示されません。コンテナ。


その基本的な知識をカバーした上で、考えられる解決策の1つは、ワークフローを再設計して、ホストにコピーされたイメージからディレクトリの内容を取得することです。まず、イメージ内の別の場所にファイルをコピーする必要があります。次に、コンテナの起動時に、保存されたイメージの場所からボリュームマウントの場所にファイルをコピーする必要があります。後者を行うときは、ボリューム(永続性)を持つという目的を無効にしていることに注意する必要があります。コピーを実行するときに、より選択的なロジックを追加することを検討してください。まず、次のようなエントリポイント.shをビルドに追加します。

#!/bin/sh
# copy from the image backup location to the volume mount
cp -a /usr/src/app_backup/node_modules/* /usr/src/app/node_modules/
# this next line runs the docker command
exec "$@"

次に、エントリポイントとバックアップコマンドを含めるようにDockerfileを更新します。

FROM node:6.3

# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# Install app dependencies
COPY package.json /usr/src/app/
RUN npm install -g babel babel-runtime babel-register mocha nodemon
RUN npm install

# Bundle app source
COPY . /usr/src/app
RUN cp -a /usr/src/app/. /usr/src/app_backup

EXPOSE 1234
ENTRYPOINT [ "/usr/src/app/entrypoint.sh" ]
CMD [ "npm", "start" ]

そして、docker-compose.ymlから余分なボリュームをドロップします。

  volumes:
    - .:/usr/src/app
10
BMitch

変化する:

  volumes:
    - .:/usr/src/app
    - /usr/src/app/node_modules

TO:

  volumes:
    - .:/usr/src/app

そして、node_modulesをローカルのマップされたボリュームに配置します。あなたがそれを持っている方法、/usr/src/app/node_modulesは、必要な別のボリュームに保存されますdocker inspect {container-name}場所を検索します。場所を指定する場合は、次のように指定します。

- /path/to/my_node_modules:/usr/src/app/node_modules

0
ldg