Windows上的Docker中的Node.js开发环境

提问

我已经尝试了所有我能想到的.我已经阅读了文档,博客,并尝试在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 Terminal中的同一位置运行它.我使用哈希,因为标记由于某些原因而没有使用:

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 scripts来运行以创建/usr/src / app目录并运行npm install

然后,server.js和package.json就是您编写的样子.它们都和Dockerfile都在同一个工作目录中.

接下来我们建立图像

docker build -t dockernodetest .

我已经省略了dockerfile标记,因为它似乎不必要.客户端仍将自动添加最新标签.要查看您在本地运行了哪些映像,请运行docker映像.

在这一点上,我们应该已经准备好运行映像,但是让我们首先检查要加载的文件是否已经存在,以及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”],因此默认操作是运行启动包脚本.

因此,为了使开发周期更快,您想通过-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映像,尽管您可能想使用诸如nodemon之类的东西使它更加无缝.