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

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

ただいまの
回答率

90.48%

  • Node.js

    2415questions

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

  • Docker

    1082questions

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

  • Visual Studio Code

    447questions

    Visual Studio Codeとは、Microsoft社が開発したマルチプラットフォーム対応のテキストエディタです。Visual Studioファミリーの一員でもあります。拡張性とカスタマイズ性が高く、テキストエディタでありながら、IDEと遜色ない機能を備えることができます。

  • docker-compose

    256questions

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

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,062

yuukive

score 32

実現したいこと

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コマンドはキャッシュが効くようにアプリコードより先に単体でコピーしています。

FROM node:10.11.0-alpine
ENV APP_ROOT /app/

WORKDIR $APP_ROOT
# アプリコードの変更の影響を受けないように先にコピー
COPY package*.json $APP_ROOT
RUN npm install

COPY . $APP_ROOT

docker-compose.yml

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

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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+3

ローカルに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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

+2

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

docker-compose.yml

version: '3.4'
services:
  web:
    image: node:10.11.0-alpine
    command: "npm run dev"
    ports:
      - '3000:3000'
    volumes:
      - .:/app

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

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

$ cd app
$ npm install

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


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

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

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

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/08 18:41

    回答ありがとうございます。

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

    質問文の要件は「dockerコンテナ内のnode_modulesをホスト側に同期したい」
    ですので、「`npm install`は常にコンテナ内で行う」で要件満たせました。

    コンテナ内のnpm installでホスト側にもnode_modulesが出来上がってましたが、
    VSCodeがうまくファイルを読み込めておらず同期されていないと勘違いしていました。
    VSCode再起動することでnode_modules内も読み込まれ、インテリセンスも
    効くようになりました。ポカミスで申し訳ないです。

    キャンセル

  • 2019/01/08 18:41 編集

    > 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オプションが半ば必須になるというのは理由があるのでしょうか。

    キャンセル

  • 2019/01/08 18:51

    > package*.jsonを先にコピーしてアプリコードの変更がnpm installのレイヤーに影響を及ぼさないようにしていました。
    https://dev.classmethod.jp/tool/docker/docker-build-meetup-1/
    copyやaddが挟まると後続のDockerキャッシュに影響が出てくるんですね。
    これは私の仕様の勘違いです、申し訳ない。

    これに関しては質問文のやり方が完全に正しいですね。
    別に--no-cacheオプションも不要です。

    懸念がかなり減りましたね。
    ただまぁ、masterブランチが変わったら誰かが勝手に追従してくれると嬉しいのでCIは使った方が良さそうですね。
    回答を修正しておきます。

    キャンセル

同じタグがついた質問を見る

  • Node.js

    2415questions

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

  • Docker

    1082questions

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

  • Visual Studio Code

    447questions

    Visual Studio Codeとは、Microsoft社が開発したマルチプラットフォーム対応のテキストエディタです。Visual Studioファミリーの一員でもあります。拡張性とカスタマイズ性が高く、テキストエディタでありながら、IDEと遜色ない機能を備えることができます。

  • docker-compose

    256questions