Doker的开发:常见问题及解决方法
原文链接: Docker for Development: Common Problems and Solutions (翻译:Bruce.Chen)
从开发环境Dev到生产环境Prod已经开始用docker了吗? 这里有一些hacky用来解决开发中的常见问题。有些只适用于VirtualBox,其他的则没有限制。
端口转发到主机
端口转发只能用在boot2docker下的VM。 如果你也想用同一端口转发到你的主机,比如你正在测试Android应用程序的后台或者想分享VM呢?
你有两个选择:
1 — 到VirtualBox的设置里去添加一个Bridged adapter。 现在当你再启动docker-machine,你的VM就会得到一个正式的LAN地址。 这时你就可以从网络上的其他任何设备访问虚拟机,而且docker-compose的端口转发也可以使用。
2 — 等到 Issue #691 (或相关)得到解决。 就可以允许你使用SSH端口转发。唯一的问题是你必须手动的操作需要的每一个端口。
docker-machine ssh -L <host-port>:localhost:<machine-port>
性能低
默认情况下,当你用docker-machine创建一个VM,只得到非常低的配置(1CPU,1GB RAM)。 运行“docker-machine help create”去了解相应的flags后,就可用它们来增加CPU/RAM。 例如:
docker-machine create \ --driver virtualbox \ --virtualbox-cpu-count 2 \ --virtualbox-memory 2048 \ dev
符号链接错误
有多种原因导致 这种 错误发生,但是最常见的一种是VirtualBox缺少 Guest Additions 。 请确定它被安装了(VirtualBox > Preferences > Extensions)并要匹配VirtualBox的版本。 这大多发生在VirtualBox是单独安装的。
共享文件夹不能得到更新
在boot2docker中,这是一个 已知的bug 。因为它为了考虑提升速度而只是缓存NFS文件。所以你需要刷新文件系统缓存。
docker-machine ssh <name-of-your-machine> sudo cache-clear (OR) sudo su
echo 3 > /proc/sys/vm/drop_caches}}}
有些commands/languages忽略FS的缓存。 例如,当运行npm,less, vi,等等,你将不会发现这些错误。但其他的命令都使用缓存 —cat,python,Apache SendFile,等等。
在VirtualBox中,这个问题也涉及到[Apache SendFile bug](https://www.virtualbox.org/ticket/9069)。
网络错误
有时你会看到怪异的网络错误,像地址不能解析,不能ping通,等等。通常是由于主机的网络配置被更改了(例如,你切换到了WiFi网络等),这时可以重启VM获得更新过的网络配置。
构建和相关性
你的Dockerfile通常被用来编译和构建应用,并准备启动。 当以volume去挂载你的文件夹(如通常在开发的情况下),这会导致各种问题。
1—有些语言(Ruby, Python, 等等)的安装依赖于用户目录的共享文件夹。 其他的(Node/NPM)直接在当前的应用程序文件夹 中安装。 因此,尽管构建容器的时候有“npm install“,但以后当你用共享的volume运行“docker- compose up”,“node_modules”文件夹消失了!
2—类似的,build文件夹也没了。 结果,容器用来启动应用的CMD多数情况下就不能工作。
这是棘手的,即使你在dev和prod用不同的Dockerfiles。 因为这不是一个build image时的问题,而是一个容器的运行时 的问题。 目前的解决方法依赖于你的语言(rake/grunt/gulp/fabric/etc)对应的Task runner,并在docker的 CMD中用它去开发。 不要在Dockerfile中填写应用的“build”逻辑,相反地请使用task runner。
{{{# gulp/grunt/rake/...
# have a "build" task
Dockerfile
# used for normal production deployment
# here you use separate tasks as needed
COPY package.json /myapp/
RUN npm install
COPY . /myapp
RUN gulp build
CMD ["npm", "start"]
docker-compose
# when developing, combine all the above commands
myservice:
volumes: ".:/myapp"
command: "sh -c 'npm install && gulp build && npm start'"
.dockerignore
确定你的“.dockerignore”文件在跨平台时能忽略常见的特殊文件。 这些不必要的文件将无效docker的构建缓存。 有了正确的”.dockerignore“的文件,build的时候你可以简单地运行”COPY ./myapp“去复制你的整个app源代码,而不是一个文件夹又一个文件的去复制。
# Ignore .git folder .git*
Ignore all Windows, Linux and OSX special files
https://www.gitignore.io/api/windows ,linux,osx,vim
Ignore all your language-specific build folders
build/
target/
node_modules/
.bundler/
etc
使用 gitignore.io 获取对应语言/平台的常见文件清单。 但请记住,”.gitignore”和”.dockerignore”甄别这些文件的方式不同。 Dockerignore要求整个文件名必须匹配。 所以在gitignore里,你可以写”node_modules“去忽略整个文件夹,但在dockerignore你不得不 用”node_modules/*“。
清理
下面的 docker-clean命令可以删除所有没有tag的image和停止的容器。 可定期运行该命令去清理VM。
docker ps -aqf status=exited | xargs docker rm docker images -qf dangling=true | xargs docker rmi
单元测试/ CI
可以用一个单独的docker-compose.test.yml,从平常的”docker-compose.yml“去” extend “服务,但这只是直接覆盖“command”set来运行测试。 然后在CI上,运行以下命令:
docker-compose -f docker-compose.test.yml run <service_name>
这将直接启动所有的链接服务,并运行测试,然后会用你的测试脚本的状态码退出。 现在,您的CI可以简单地安装docker-compose,并可以为每个服务运行上面的命令而不需要了解特定的服务!
链接
当运行测试时,docker-compose很容易把所有的微服务链接在一起。 对于pet项目,这通常不是问题,但对于规模较大的项目就比较头痛。 尽早避免它, 可以像 stubby4node 那样,用一个描述stubbed endpoints的简单的YAML文件去使用stub servers。
时钟同步错误
当docker-machine VM的时钟与实际时间不同步,你会得到很多奇怪的错误,如签名错误(各种AWS服务)。 在这种情况下,只要重新启动该VM去同步时钟。 这通常发生在暂停/恢复你的笔记本电脑或台式机。 你的主机操作系统更新了时间,但挂起的VM却滞后了。 同样的情况对于Vagrant也是如此。
忘记关闭虚拟机
”无耻的plug“:当我们正在Docker上开发一个菜单栏的应用程序,我们往往在离开时让docker-machine VM一直运行,忘记将其关闭。 看一看 — github.com/rdsubhas/docker-menu !