在开发流程中使用Docker

12
我在Mac上使用boot2docker,并克隆了以下存储库:https://github.com/enokd/docker-node-hello。它基本上有一个Dockerfile和一个非常简单的express应用程序,打印出hello world。当我构建并运行镜像时,一切都很顺利,但是如果我在我的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+和fig的更多当前答案。


我已经为此编写了Docker Shell。请参见http://dockershell.io/。 - mzedeler
4个回答

7
Your question is really interesting, and (partially) not specifically related to Docker. Let me say that the main and final problem here is the use of a virtual machine.
Tracking code changes on host computer can be a challenge when you use a VM (bare Virtualbox VM, Vagrant VM, Docker boot2docker VM...)
The VM is a complete layer of abstraction between your Mac (where your code changes happen) and your application stack (here, the Docker container running on a tiny Linux VM).
- You have to explicitly define a shared folder (NFS, ...) in Virtualbox, between your Mac and boot2docker. This shared folder would be the root of your code repository. That's the first step. Mac: /Users/You/stuff/approot ===> boot2docker: /something


  • 然后,您需要告诉Docker容器使用绑定在boot2docker上的(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


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

  • 此外,由于更改不发生在本地文件系统上,而是发生在共享文件夹上,您可能需要告诉Nodejs监视器(Forever/Nodemon/...)使用轮询模式。它可以工作(或多或少),但会消耗大量CPU。


1
我一直在寻找(或者希望有可能)的答案是,在主机操作系统中运行一个监视器,自动更新镜像(即以某种方式重新运行ADD命令)。 - Abdullah Jibaly
2
是的,这就是为什么我认为重新构建镜像可能只有在您想要分享或部署您的工作时才会发生:这种情况比每次文件编辑后都发生的情况少。 - mbarthelemy
2
是的,几乎所有的东西都会被缓存起来,但最终你会得到成百上千个缓存的中间图像。顺便问一下,如果您不想部署它,每次更改后重建图像有什么意义呢? - mbarthelemy
1
我理解,基本上我也对你所感兴趣的工作流程有相同的兴趣。但我仍不确定你想要的是否有意义(在每次代码更改时持续重建容器)。或者,可以使用容器在开发和生产环境中拥有完全相同的环境(系统、服务和应用程序),但在开发和生产环境中都将代码分离到Docker卷中。 - mbarthelemy
1
回答了这个问题并分享了我的解决方案,非常希望听到您的反馈。 - Abdullah Jibaly
显示剩余6条评论

5
关于使用VirtualBox共享文件夹,请查看以下内容:
boot2docker和VirtualBox Guest Additions一起使用
如何将/Users挂载到boot2docker中。
https://medium.com/boot2docker-lightweight-linux-for-docker/boot2docker-together-with-virtualbox-guest-additions-da1e3ab2465c

简而言之,构建带有VirtualBox Guest Additions的自定义boot2docker.iso(参见链接)或下载http://static.dockerfiles.io/boot2docker-v1.1.0-virtualbox-guest-additions-v4.3.12.iso并将其保存到~/.boot2docker/boot2docker.iso。

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

1
最好能够在某个地方放置一个链接,指向您的最新ISO文件,而不是v1.0.1,因为随着时间的推移,它将会发生变化。 - Larry Cai

4

这是我最终做的事情,目前看起来有效,但我仍在深入研究:

# 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

感谢这个来源

针对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 install,以便任何私有包都能正常工作。此外,这与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镜像是正确的方式? - mattes
1
我也在Docker中进行开发,效果非常好。它基本上是我上面所说的版本的增强版,但是我没有直接运行nodemon,而是编写了一个脚本,使用nodemon作为库,在将其发送到Docker构建上下文之前正确设置项目。这使我能够做一些事情,比如同时拉取我正在开发的依赖项目。 - Abdullah Jibaly
@mattes FYI,我更新了答案,其中包含与我当前工作流程相当接近的内容。 - Abdullah Jibaly
在这个设置中,你使用文件系统监视器有什么运气或成功吗? - David Souther
我猜你是在使用Linux主机进行这项操作。我们苦逼的OSX用户没那么幸运。 - David Souther
显示剩余2条评论

0

有几种场景可以使用Docker来帮助Web开发:

  1. 快速提供各种本地服务。你想要一个干净的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. 管理软件依赖项。例如,您想在不同的node版本(0.8、0.10、0.10.25等)下运行您的node应用程序,只需通过docker search nodejs查找nodejs docker镜像,并通过挂载应用程序目录作为卷创建容器,您可以运行多个相互隔离的容器。看看我的keystonejs-example项目,了解如何在几秒钟内使用0配置运行复杂的node应用程序和mongodb。考虑更复杂的模型:负载均衡器+应用程序+数据库+缓存,在老式的方式中,有大量的配置选项来适应设置过程,但是,如果将它们作为单独的容器提供,并通过名称链接连接,每个组件都可以通过本地环境变量发现彼此,就像本地PaaS一样。

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

根据boot2docker,我猜你在使用OSX,所以最好选择v0.9.2+版本,该版本支持hostonly网络配置,这样你就可以通过hostonly网络访问在虚拟机中运行的容器了。

2
我知道你列出的三个功能,它们都是很棒的功能,但我的问题实际上与此无关。我真正感兴趣的是如何在Docker环境中进行迭代开发。我该如何在文本编辑器或IDE中进行更改并看到我的Docker环境反映出来。 - Abdullah Jibaly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接