【问题标题】:Using docker during the development workflow在开发工作流程中使用 docker
【发布时间】:2015-01-07 15:15:00
【问题描述】:

我在 OS X 上使用 boot2docker 并克隆了以下 repo:

https://github.com/enokd/docker-node-hello

它基本上有一个 Dockerfile 和一个打印 hello world 的非常简单的 express 应用程序。当我构建和运行映像时,一切都运行良好,但当然,如果我在我的 Mac 上对 index.js 进行任何更改,这些都不会反映在我正在运行的映像中。我似乎找不到任何关于如何设置 docker 的参考资料,以便我可以在我的开发环境中运行它以自动获取我的源代码更改,所以我觉得我“做错了”。有什么建议吗?

这是我目前的运行方式(我没有使用 Vagrant,不太确定这是否有什么不同):

$ docker build -t gasi/centos-node-hello .
$ docker run -p 49160:8080 -d gasi/centos-node-hello
$ curl localhost:49160

更新:添加了我最终所做的答案。

更新:使用 boot2docker 1.3+ 和图添加了更多当前答案。

【问题讨论】:

标签: node.js docker boot2docker


【解决方案1】:

您的问题真的很有趣,并且(部分)与 Docker 无关。 让我说,这里主要和最后一个问题是虚拟机的使用。

当您使用 VM(裸 Virtualbox VM、Vagrant VM、Docker boot2docker VM...)时,跟踪主机上的代码更改可能是一项挑战

VM 是 Mac(发生代码更改的地方)和应用程序堆栈(这里是运行在微型 Linux VM 上的 Docker 容器)之间的完整抽象层。

  • 您必须在您的 Mac 和 boot2docker 之间的 Virtualbox 中明确定义一个共享文件夹(NFS,...)。此共享文件夹将是您的代码存储库的根目录。这是第一步。

    Mac:/Users/You/stuff/approot ===> boot2docker/something


  • 然后,您必须告诉 Docker 容器使用绑定到 boot2docker 的 Volume(docker 术语),并将 Docker 应用程序指向它:
docker run -v /something:/app/path/inside/docker -p 49160:8080 \ -d gasi/centos-node-hello /usr/bin/node /app/path/inside/docker/index.js


  • 让 NodeJ 检测文件更改是另一个挑战。您需要一个额外的包装器来监视文件系统并在代码更改时重新启动 Node(ForeverNodemon...)。

  • 而且,在那之后,由于更改不会发生在本地文件系统上,而是发生在共享文件夹上,您可能必须告诉 Nodejs 观察程序 (Forever/Nodemon/...) 使用轮询模式。它可以工作(或多或少),但会消耗大量 CPU。

【讨论】:

  • 我正在寻找的答案(或者可能希望是可行的)将类似于在主机操作系统中运行一个观察程序,它会自动更新图像(即,重新运行 ADD 命令以某种方式)。
  • 是的,这就是为什么我说,在我看来,重建映像应该只在您想要共享或部署您的工作时发生:这种情况发生的频率低于每次编辑文件后发生的频率。跨度>
  • 是的,几乎所有内容都会被缓存,但您最终会在一天结束时获得数百个缓存的中间图像。顺便说一句,如果您不想部署它,那么在每次更改后重新构建映像有什么意义?
  • 我了解,基本上我也或多或少对与您完全相同的工作流程感兴趣。仍然不确定您想要的是否有意义(在每次代码更改时不断重建容器)。或者可以使用容器为 dev 和 prod(系统、服务和应用程序)提供完全相同的环境,但在 dev 和 prod 的 Docker 卷上保持代码分开。
  • 用我最终做的事情回答了这个问题,很想听听您的任何反馈。
【解决方案2】:

关于VirtualBox的共享文件夹,请查看:

boot2docker 和 VirtualBox Guest Additions
如何将 /Users 挂载到 boot2docker

https://medium.com/boot2docker-lightweight-linux-for-docker/boot2docker-together-with-virtualbox-guest-additions-da1e3ab2465c

tl;dr 使用 VirtualBox Guest 构建您自己的自定义 boot2docker.iso 添加(见link)或下载 http://static.dockerfiles.io/boot2docker-v1.1.0-virtualbox-guest-additions-v4.3.12.iso 并将其保存到 ~/.boot2docker/boot2docker.iso。

编辑:更新了 boot2docker v1.1.0 的链接

【讨论】:

  • 如果能在某个地方有一个指向您最新 iso 而不是 v1.0.1 的链接会很高兴,因为它会随着时间的推移而改变
【解决方案3】:

这就是我最终做的事情,到目前为止似乎可行,但我仍在深入研究:

# script located in bin/run
NS=mycompany
PROJECT=myproject

# kill and remove old container if it exists
docker kill $PROJECT
docker rm $PROJECT

# tag the previously built image
docker tag $NS/$PROJECT $NS/$PROJECT:old

# build the new image
docker build -t $NS/$PROJECT .

# remove the old image
docker rmi $NS/$PROJECT:old

docker run -dP --name=$PROJECT $NS/$PROJECT /sbin/my_init

在我的项目根目录中,我只需运行:

nodemon -x bin/run

归功于source

docker 1.3 和 fig 更新

Fig 很棒,它确实从我以前的脚本中消除了很多复杂性。此外,boot2docker 现在原生支持使用 Virtual Box 的共享文件夹在 Mac OS X 上挂载卷。这就是我发现现在对我非常有效的方法:

首先,Dockerfile

FROM ubuntu:14.04

# Replace shell with bash so we can source files
RUN rm /bin/sh && ln -s /bin/bash /bin/sh

# Set debconf to run non-interactively
RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections

# Install base dependencies
RUN apt-get update && apt-get install -y -q --no-install-recommends \
        build-essential \
        ca-certificates \
        curl \
        git \
        libssl-dev \
        python \
        rsync \
        software-properties-common \
        wget \
    && rm -rf /var/lib/apt/lists/*

ENV NVM_DIR /usr/local/nvm
ENV NODE_VERSION 0.10.33

# Install nvm with node and npm
RUN curl https://raw.githubusercontent.com/creationix/nvm/v0.20.0/install.sh | bash \
    && source $NVM_DIR/nvm.sh \
    && nvm install $NODE_VERSION \
    && nvm alias default $NODE_VERSION \
    && nvm use default

ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
ENV PATH      $NVM_DIR/v$NODE_VERSION/bin:$PATH

CMD ["npm", "start"]

fig.yml:

app:
    image: myNodeImage
    working_dir: /home/myProject
    volumes_from:
     - myvols

这是新的bin/run

#!/usr/bin/env bash
# This is the the bin/run script

docker run --rm --volumes-from myvols myNodeImage \
    rsync \
        --delete \
        --recursive \
        --safe-links \
        --exclude .git  --exclude node_modules  \
    /data/myProject/ /home/myProject

fig up

我还有一个 bin/install 脚本,用于安装 node_modules 依赖项。这假设我已经在我的主机上完成了 npm 安装,以便任何私有包都可以工作。此外,这适用于 npm 链接,您只需要将符号链接从您的 /home/linkedProject 链接到容器中的 $NODE_PATH/linkedProject

#!/usr/bin/env bash
# This is the the bin/install script

docker run --rm --volumes-from myvols myNodeImage \
    rm -rf /home/myProject && \
    rsync \
        --delete \
        --recursive \
        --safe-links \
        --exclude .git \
        /data/myProject/ /home/myProject && \
    cd /home/myProject && \
    npm rebuild

所以,为了把这一切放在一起,以下是按顺序排列的步骤:

  1. 创建我的数据卷容器:

    docker run -v $HOME/data:/data:ro \ -v /home \ -v /path/to/NODE_PATH \ --name myvols myNodeImage echo Creating my volumes

  2. 运行我的安装脚本:cd ~/data/myProject && ./bin/install

  3. 运行我的运行脚本:nodemon -x bin/run

【讨论】:

  • 有趣的方法。所以你认为一旦你想部署它就开发本地并构建一个 docker 镜像是要走的路吗?
  • 我实际上也在 docker 内部进行开发,而且效果很好。它基本上是我上面所拥有的涡轮增压版本,但我没有直接运行nodemon,而是创建了一个使用nodemon 作为库的脚本,并在将项目发送到docker构建上下文之前做了很多事情来正确设置项目.这让我可以做一些事情,比如拉入我正在同时处理的依赖项目。
  • @mattes 仅供参考,我用与我当前工作流程非常接近的内容更新了答案。
  • 在此设置中使用文件系统观察程序是否有任何运气或成功?
  • @DavidSouther 是的,我正在使用nodemon,如上所述。它看起来像:nodemon -x bin/run
【解决方案4】:

Docker 可以在以下几种情况下帮助 Web 开发:

  1. Lighting 在本地快速提供所有不同类型的服务。你想要一个干净的couchdb,运行docker run -d -p 5984:5984 tutum/couchdb; mysql,没问题:docker run -d -p 3306:3306 tutum/mysql,一个带firefox的selenium服务器?简单:sudo docker run -p 4444:4444 -d lzhang/selenium,你会立即得到它们,它们可以在你不想要它们的下一秒被docker kill 摧毁。非常适合本地测试场景,不用担心如何配置。

  2. 管理软件依赖项。例如,您想在不同的节点版本(0.8、0.10、0.10.25 等)下运行您的节点应用程序,只需通过docker search nodejs 找到 nodejs docker 镜像,并通过将您的应用程序目录挂载为卷来创建容器,您可以运行多个相互隔离的容器。看看我的keystonejs-example 项目,了解如何使用 mongodb 在几秒钟内以 0 配置运行复杂的节点应用程序。考虑一个更复杂的模型:负载均衡器 + 应用程序 + 数据库 + 缓存,以老派的方式,有大量的配置选项来适应设置过程,但是,如果你将它们配置为单独的容器和link them by names,每个组件都可以通过本地环境变量相互发现,就像本地 PaaS。

  3. 通过搜索docker index 轻松使用应用程序。例如,有一个简洁的工具叫做Heartbleed checker,你可以通过单个命令快速下载/在容器中使用它,甚至不需要考虑配置、下载语言运行时、配置、卸载等.

根据 boot2docker,我假设您使用的是 OSX,因此您最好选择支持 hostonly 网络配置的 v0.9.2+ 版本,然后您可以通过 hostonly 网络访问在 VM 内运行的容器。

【讨论】:

  • 我知道您列出的 3 个功能,它们是很棒的功能,但我的问题与此无关。我对如何在 docker 环境中完成迭代开发非常感兴趣。如何在我的文本编辑器或 IDE 中进行更改并查看我的 docker 环境反映了这一点。
猜你喜欢
  • 2015-12-16
  • 1970-01-01
  • 1970-01-01
  • 2016-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多