質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
docker-compose

docker-composeとは、複数のコンテナで構成されるサービスを提供する手順を自動的し管理を簡単にするツール。composeファイルを使用しコマンド1回で設定した全サービスを作成・起動することが可能です。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

Q&A

解決済

2回答

12888閲覧

dockerコンテナ内のnode_modulesをホスト側に同期したい

yuukive

総合スコア40

docker-compose

docker-composeとは、複数のコンテナで構成されるサービスを提供する手順を自動的し管理を簡単にするツール。composeファイルを使用しコマンド1回で設定した全サービスを作成・起動することが可能です。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

3グッド

2クリップ

投稿2019/01/07 10:24

編集2019/01/07 10:27

実現したいこと

VSCodeを使用してexpress.jsアプリの開発を行っています。
コンテナ内のみにnode_modulesが存在する場合、VSCodeがライブラリを発見できなくて
インテリセンスが動かない(下記画像のようにCannot find module 'xxx'となる)ため、
docker-compose build した際に出来上がるコンテナ内のnode_modulesをホスト側に同期し、
コンテナ内でnpm installをするたびにホスト側にも反映されるようにしたいです。
ライブラリが発見できない

手っ取り早い方法としてはホスト側でもnpm installするという方法もあるかと思いますが、
ライブラリ更新のたびにホストとコンテナで二重に実行する必要があるのでできれば避けたいです。
また、ホスト側のNode.jsバージョン等の影響をコンテナ側に持ち込みたくないため、同期の方向は
ホスト→コンテナではなくコンテナ→ホストとしたいです。

現状のDockerfileとdocker−composeファイル

Dockerfile

npm installコマンドはキャッシュが効くようにアプリコードより先に単体でコピーしています。

dockerfile

1FROM node:10.11.0-alpine 2ENV APP_ROOT /app/ 3 4WORKDIR $APP_ROOT 5# アプリコードの変更の影響を受けないように先にコピー 6COPY package*.json $APP_ROOT 7RUN npm install 8 9COPY . $APP_ROOT

docker-compose.yml

掲題の問題とは別に、docker-compose up時にappディレクトリをマウントすると、
ホスト側にnode_modulesが無いのでコンテナ内のnode_modulesが消失してしまう
という問題があるため、それを回避するために以下のように作成しました。

yml

1version: '3.4' 2services: 3 web: 4 build: 5 context: . 6 command: "npm run dev" # 詳細省きますがexpressサーバーを起動してるだけです 7 ports: 8 - '3000:3000' 9 volumes: 10 - .:/app 11 - /app/node_modules # 消失対策

上記のDockerfile、docker-composeをベースに、コンテナ内で実行したnpm installをホスト側(のアプリディレクトリ内)にも
反映する設定方法があればご教授いただきたいです。

isoken26, segur, 10JII_K👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ローカルにVSCodeとNode.jsをインストールしている時点で
環境を汚さないとか言ってても理想と現実がもう相当剥離してるんですが???状態になってます。

なので、ローカルにnode_modulesを作るという運用は避けられないでしょう。

非常に同意するところで、過剰に環境に拘るといつまでたってもアプリケーションコードを書き始められないのでほどほどにした方が良いかと。
どうしてもDockerで開発を完結させたいのであればマウントせずにコンテナ内でvimで開発するという手もあります。

本題ですが、マウントの瞬間はホスト優先ですが、マウント後は双方向同期です。

docker-compose build --no-cache docker-compose up -d docker-compose exec コンテナ名 bash

コンテナを起動後に中に入り、

npm i

を実行すればコンテナ内のNode.jsランタイムでnode_modulesをインストールできます。
マウント後なのでホスト側にも同期されます。

先日似たような質問に回答しました。

https://teratail.com/questions/166298#reply-249054

投稿2019/01/07 14:37

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

もうこんな風にローカルは生のalpine使って、
DroneみたいなCIツールにDockerBuildさせるような構成にしたほうがいいです。

docker-compose.yml

yaml

1version: '3.4' 2services: 3 web: 4 image: node:10.11.0-alpine 5 command: "npm run dev" 6 ports: 7 - '3000:3000' 8 volumes: 9 - .:/app

ローカルにVSCodeとNode.jsをインストールしている時点で
環境を汚さないとか言ってても理想と現実がもう相当剥離してるんですが???状態になってます。
なので、ローカルにnode_modulesを作るという運用は避けられないでしょう。

質問文の要件はみたせませんが、今の所これが自然かつモアベターな方法です。

bash

1$ cd app 2$ npm install

もし何か完璧な案を思いついたら試してみて下さい。


ライブラリ更新のたびにホストとコンテナで二重に実行する必要があるのでできれば避けたいです。

これはおっしゃる通り。
実はモダンなプロジェクトではエンジニアが手作業でビルドすることは避けています。
(何が混入するかわからんし)

簡易的にやるならDockerHubとGitHubを連携させて、masterブランチが更新されたら自動的にdocker buildが走ってイメージが更新されるということが可能ですし、
凝ったことがしたければWebhookからDrone等のCIツールを発火させて自動ビルドするような仕組みを構築しましょう。

その場合はnode_modulesディレクトリは.gitignore配下に含まれるはずで、
.dockerignoreで指定する必要すらなくなります。

GitHubなんかのmasterブランチが更新されたら、
CIツールが実行されて自動的にDockerImageが更新される。
これが勝ちパターンなので是非DroneやDockerHubの機能を覚えてみてください。

投稿2019/01/07 11:07

編集2019/01/08 09:52
miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuukive

2019/01/08 09:41

回答ありがとうございます。 > 質問文の要件はみたせませんが、今の所これが自然かつモアベターな方法です。 質問文の要件は「dockerコンテナ内のnode_modulesをホスト側に同期したい」 ですので、「`npm install`は常にコンテナ内で行う」で要件満たせました。 コンテナ内のnpm installでホスト側にもnode_modulesが出来上がってましたが、 VSCodeがうまくファイルを読み込めておらず同期されていないと勘違いしていました。 VSCode再起動することでnode_modules内も読み込まれ、インテリセンスも 効くようになりました。ポカミスで申し訳ないです。
yuukive

2019/01/08 09:42 編集

> npm installコマンドの結果はpackage.jsonとpackage-lock.jsonの状態で一意に決まるべきなので、 > コマンドの文字列のみで判断するDockerにキャッシュを作ってもらうのはナンセンスです。 > ビルド時に--no-cacheオプションは半ば必須になりますから、 > 上記の理由で「キャッシュが効くように先にコピー」というのが全くメリットとして機能していません。 DockerのCI/CD運用を探すとできるだけ多くのレイヤーをキャッシュして cache-from等を使いビルド時間を短縮する方向の記事がたくさん出てくるので、 [Node.js公式](https://nodejs.org/en/docs/guides/nodejs-docker-webapp/#creating-a-dockerfile) のDockernizeドキュメントを参考に package*.jsonを先にコピーしてアプリコードの変更がnpm installのレイヤーに影響を及ぼさないようにしていました。 (実際、更新頻度は アプリコード更新 >>> package.json更新 なので、結構な頻度でビルド時間が短縮できています。) 状況によりけりかもしれませんが、ビルド時に--no-cacheオプションが半ば必須になるというのは理由があるのでしょうか。
miyabi-sun

2019/01/08 09:51

> package*.jsonを先にコピーしてアプリコードの変更がnpm installのレイヤーに影響を及ぼさないようにしていました。 https://dev.classmethod.jp/tool/docker/docker-build-meetup-1/ copyやaddが挟まると後続のDockerキャッシュに影響が出てくるんですね。 これは私の仕様の勘違いです、申し訳ない。 これに関しては質問文のやり方が完全に正しいですね。 別に--no-cacheオプションも不要です。 懸念がかなり減りましたね。 ただまぁ、masterブランチが変わったら誰かが勝手に追従してくれると嬉しいのでCIは使った方が良さそうですね。 回答を修正しておきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問