簡體   English   中英

Windows上的Docker中的Node.js開發環境

[英]Node.js dev environment in Docker on Windows

我已經嘗試了我能想到的一切。 我已閱讀文檔,博客並嘗試在github上進行以下示例。

但我似乎無法讓它發揮作用。

我想做的很簡單。 我想在我的Windows 8.1機器上編寫我的node.js代碼,我還想從Docker容器中運行代碼,而不必一直重建容器。 所以我想將Windows主機上的目錄映射到容器內的目錄。

我創建了這個Dockerfile

FROM node:0.10.38

RUN apt-get update -qq && apt-get install -y build-essential

ENV ZMQ_VERSION 4.1.3
ENV LIBSODIUM_VERSION 1.0.3

RUN curl -SLO "https://download.libsodium.org/libsodium/releases/libsodium-$LIBSODIUM_VERSION.tar.gz" \
    && tar xvf libsodium-$LIBSODIUM_VERSION.tar.gz \
    && cd libsodium-$LIBSODIUM_VERSION \
    && ./configure \
    && make \
    && make install \
    && cd .. \
    && rm -r libsodium-$LIBSODIUM_VERSION \
    && rm libsodium-$LIBSODIUM_VERSION.tar.gz
RUN curl -SLO "http://download.zeromq.org/zeromq-$ZMQ_VERSION.tar.gz" \
    && tar xvf zeromq-$ZMQ_VERSION.tar.gz \
    && cd zeromq-$ZMQ_VERSION \
    && ./configure \
    && make \
    && make install \
    && cd .. \
    && rm -r zeromq-$ZMQ_VERSION \
    && rm zeromq-$ZMQ_VERSION.tar.gz
RUN ldconfig

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

RUN mkdir -p /usr/src/app
ADD . /usr/src/app
WORKDIR /usr/src/app
RUN npm install

EXPOSE 3000
EXPOSE 35729

CMD ["npm", "start"]

我有這個簡單的server.js文件

var express = require('express');
var app = express();
var zmq = require('zmq');

app.get('/', function (req, res) {
  res.send('ZMQ: ' + zmq.version);
});

var server = app.listen(3000, function () {
  var host = server.address().address;
  var port = server.address().port;

  console.log('Example app listening at http://%s:%s', host, port);
});

而這個簡單的package.json

{
  "name": "docker-node-hello-world",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.13.3",
    "zmq": "^2.14.0"
  }
}

我安裝了最新的Docker Toolbox,可以運行Docker Hello World示例。 當我在Dockerfile所在的目錄中時,我嘗試構建這樣的docker鏡像。

docker build -t dockernodetest:dockerfile .

然后我嘗試從Docker Quickstart終端內的相同位置運行它。 我使用哈希,因為標簽不出於某種原因:

docker run -v //c/Bitbucket/docker-node-hello-world/:/usr/src/app -p 3000:3000 -i -t 9cfd34e046a5 ls ./usr/src/app

結果是一個空目錄。 我希望我可以調用

docker run -v //c/Bitbucket/docker-node-hello-world/:/usr/src/app -p 3000:3000 -i -t 9cfd34e046a5 npm start

但由於主機目錄不可用,因此失敗。 我覺得我誤解了一些非常基本的東西。 我只是不知道是什么。

首先讓我們從Dockerfile開始

FROM node:0.10.38-onbuild

RUN apt-get update -qq && apt-get install -y build-essential

ENV ZMQ_VERSION 4.1.3
ENV LIBSODIUM_VERSION 1.0.3

RUN curl -SLO "https://download.libsodium.org/libsodium/releases/libsodium-$LIBSODIUM_VERSION.tar.gz" \
    && tar xvf libsodium-$LIBSODIUM_VERSION.tar.gz \
    && cd libsodium-$LIBSODIUM_VERSION \
    && ./configure \
    && make \
    && make install \
    && cd .. \
    && rm -r libsodium-$LIBSODIUM_VERSION \
    && rm libsodium-$LIBSODIUM_VERSION.tar.gz
RUN curl -SLO "http://download.zeromq.org/zeromq-$ZMQ_VERSION.tar.gz" \
    && tar xvf zeromq-$ZMQ_VERSION.tar.gz \
    && cd zeromq-$ZMQ_VERSION \
    && ./configure \
    && make \
    && make install \
    && cd .. \
    && rm -r zeromq-$ZMQ_VERSION \
    && rm zeromq-$ZMQ_VERSION.tar.gz
RUN ldconfig

EXPOSE 3000 35729

從第1行開始,我使用了0.10.38-onbuild標簽,因為我想利用將運行的onbuild腳本來創建/usr/src/app目錄並運行npm install

然后server.jspackage.json就像你寫的一樣。 它們也與Dockerfile位於同一工作目錄中。

接下來我們構建圖像

docker build -t dockernodetest .

我省略了dockerfile標簽,因為它似乎沒必要。 無論如何,客戶端將自動添加latest標簽。 要查看您在本地運行docker images

此時我們應該准備好運行一個映像,但是讓我們先檢查一下我們要加載的文件然后npm install創建了node_modules目錄

$ docker run dockernodetest ls /usr/src/app
Dockerfile
node_modules
package.json
server.js

我們已准備好運行我們的小nodejs應用程序

$ docker run -it -p 8080:3000 dockernodetest

> docker-node-hello-world@1.0.0 start /usr/src/app
> node server.js

Example app listening at http://0.0.0.0:3000

在這個例子中,我使用-p 8080:3000標志將容器的3000端口映射到主機上的端口8080。 請注意,我最后沒有任何其他命令,因為我提取的-onbuild圖像具有CMD [ "npm", "start" ] ,因此默認操作是運行start包腳本。

因此,為了使開發周期更快,您需要通過-v選項將工作目錄掛載到容器中

$ docker run -it -p 8080:3000 -v "$PWD":/usr/src/app dockernodetest

> docker-node-hello-world@1.0.0 start /usr/src/app
> node server.js


module.js:340
    throw err;
          ^
Error: Cannot find module 'express'
    at Function.Module._resolveFilename (module.js:338:15)
    at Function.Module._load (module.js:280:25)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (/usr/src/app/server.js:1:77)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)

npm ERR! Linux 4.1.7-15.23.amzn1.x86_64
npm ERR! argv "node" "/usr/local/bin/npm" "start"
npm ERR! node v0.10.38
npm ERR! npm  v2.11.1
npm ERR! code ELIFECYCLE
npm ERR! docker-node-hello-world@1.0.0 start: `node server.js`
npm ERR! Exit status 8

但是這里發生了什么? 因為我們掛載了當前的工作目錄,所以它覆蓋了以前在/usr/src/app包含我們的node_modules目錄的內容。

所以這里的快速解決方法是在我們當前的工作目錄中運行npm install並重新運行docker run命令。

$ npm install
docker-node-hello-world@1.0.0 /home/ec2-user/dockernode
└─┬ express@4.13.3
  ├─┬ accepts@1.2.13
  │ ├─┬ mime-types@2.1.7
...
$ docker run -it -p 8080:3000 -v "$PWD":/usr/src/app dockernodetest

> docker-node-hello-world@1.0.0 start /usr/src/app
> node server.js

Example app listening at http://0.0.0.0:3000

現在,如果您對server.js文件進行更新,只需按Ctrl + c並重新啟動docker image,盡管您可能希望使用類似nodemon的東西來使其更加無縫。

非常感謝你的回答。 這無疑使我走上了正確的道路。 我花了比我想象的更長的時間,但我得到了它的工作。

有一些事情沒有用,但我終於開始工作了。 這是我經歷過的簡要介紹。

  1. 我無法按照您的建議使用onbuild腳本。 原因是當我將我的圖像基於onbuild腳本時,它在我安裝ZeroMQ之前運行npm install

  2. 在我的docker鏡像外運行npm install不是你在映射驅動器時建議的選項。 我想在Docker中運行它的原因之一是我想要一個所有依賴項(如ZeroMQ)安裝並可用的環境。 這在某些環境中是困難的,我想在Windows和Linux主機上運行它。

  3. 我真的想在開發時使用nodemon ,所以我還必須在映像中全局安裝它,並在啟動容器時調用nodemon。 因此,我必須按照您的建議擴展您的示例。

  4. 我很難讓映射的卷工作。 事實證明,在Windows主機上,您必須位於C:\\users\\<username>的上下文中才能從容器映射主機上的卷。 有一次,我想出了所有奇怪的實驗,並完成了所有工作,我完成了工作。 在調用docker run時建議使用"$PWD"在Windows主機上也很奇怪。 你必須用這樣的正斜杠作為前綴: /"$PWD"

  5. 當我想到這一切時,我開始關注docker compose,部分是因為我不想繼續輸入長的docker run命令(我一直都錯了),但也因為在我的真實項目中我想要數據庫的多個容器和我需要的其他服務。

所以這就是現在的樣子。 它的工作方式與我希望它的工作方式完全一致。 我現在有一個容器,其中所有依賴項都安裝在容器內,每當我運行我的容器時,它首先調用npm installnodemon server.js 包括已安裝的npm模塊在內的所有文件都在主機上,但映射到運行所有內容的容器內。

文件1 - docker-compose.yml(注意我不需要$ PWD變量,但只能使用.相對路徑作為主機路徑)

web:
  build: .
  volumes:
    - ".:/usr/src/app"
  ports:
    - "3000:3000"

文件2 - Dockerfile

FROM node:0.10.40

RUN mkdir /usr/src/app
RUN mkdir /usr/src/node_modules

RUN apt-get update -qq && apt-get install -y build-essential

ENV ZMQ_VERSION 4.1.3
ENV LIBSODIUM_VERSION 1.0.3

RUN curl -SLO "https://download.libsodium.org/libsodium/releases/libsodium-$LIBSODIUM_VERSION.tar.gz" \
    && tar xvf libsodium-$LIBSODIUM_VERSION.tar.gz \
    && cd libsodium-$LIBSODIUM_VERSION \
    && ./configure \
    && make \
    && make install \
    && cd .. \
    && rm -r libsodium-$LIBSODIUM_VERSION \
    && rm libsodium-$LIBSODIUM_VERSION.tar.gz
RUN curl -SLO "http://download.zeromq.org/zeromq-$ZMQ_VERSION.tar.gz" \
    && tar xvf zeromq-$ZMQ_VERSION.tar.gz \
    && cd zeromq-$ZMQ_VERSION \
    && ./configure \
    && make \
    && make install \
    && cd .. \
    && rm -r zeromq-$ZMQ_VERSION \
    && rm zeromq-$ZMQ_VERSION.tar.gz
RUN ldconfig

RUN npm install -g nodemon
WORKDIR /usr/src/app

CMD export NODE_PATH=/usr/src/node_modules && cp package.json /usr/src && npm install --prefix /usr/src && npm start

EXPOSE 3000 35729

文件3 - package.json(注意我在調用nodemon時使用-L標志。在容器內運行時需要這樣做)

{
  "name": "docker-node-hello-world",
  "version": "1.0.0",
  "description": "node hello world",
  "main": "server.js",
  "scripts": {
    "start": "nodemon -L server.js"
  },
  "author": "Author",
  "license": "ISC",
  "dependencies": {
    "express": "^4.13.3",
    "zmq": "^2.14.0"
  }
}

文件4 - server.js

var express = require('express');
var app = express();
var zmq = require('zmq');

app.get('/', function (req, res) {
  res.send('ZMQ Version: ' + zmq.version);
});

var server = app.listen(3000, function () {
  var host = server.address().address;
  var port = server.address().port;

  console.log('Example app listening at http://%s:%s', host, port);
});

要構建使用以下命令

docker-compose build

要運行,請使用以下命令

docker-compose up

這時我可以在我的主機上開發我的應用程序,每當我更改文件時,我的節點服務器都會重新啟動。 當我向package.json添加一個新的依賴項時,我必須重啟我的容器才能運行npm install

我唯一沒有工作的是如何使我的圖像重建順利進行。 發生的事情是,在我構建新映像之后,我必須刪除舊容器才能運行新容器。 映射由舊容器鎖定。

我真的很想給你@jeedo。 沒有你的幫助,我不會達到這個解決方案。 我不知道該怎么做,並將此標記為解決方案。

編輯:我剛剛編輯了這個,以便為我的Dockerfile添加一些內容。 我將node_modules文件夾移離主機文件系統。 我在Windows上路徑變得太長時遇到了一些麻煩。 這些更改確保node_modules始終安裝在容器內。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM