Docker + Django 一周踩坑记

    鉴因而公司的项目,项目源码很差公开,就专门讲踩坑的经历好了,我之前没有接触过docker,一直觉得它是个轻量化的虚拟机,但在看了《docker - 从入门到实践》前言与介绍后,我意识到个人认识是不全面的,准确来讲,docker是一个基于操做系统内核的虚拟化技术,可以低消耗地封装你想要的进程。以往的虚拟机都是在系统上又构建了一个完整的系统,天然耗费巨大,而docker则提供了一个可让你为所欲为地称王的果壳,让每一个进程在这个果壳中都能享有一个本身的宇宙,而这个果壳又立足于真正的宇宙--操做系统内核上。mysql

    docker有三个重要概念:镜像,容器,仓库。按个人理解:linux

    镜像就是剧本,这个剧本描述了全部的场景布置(系统环境),演员结构(软件依赖),剧情设计(运行程序)等等,是果壳里这场戏的根本,没有剧本,就没有戏。nginx

    容器就是实际演出,是剧本的实现,你做为导演,若是看的不爽,能够闯入进去,进行各类调整与改变,当你调整改变完了,你想沿用下来,那就commit做为新剧本。(但官方推荐使用Dockerfile,由于能够完整地再现一个剧本的创做,至关于给剧本做说明,要否则剧本就成为了黑盒子)git

    仓库就是剧本存放箱子,各类各样的剧本都在这里,有的是同一场戏的,可是分新旧版本,你须要给剧本打上标签,标明它是哪一个版本的,最近版本就叫latest,仓库的公开服务可让你向全天下分享你的剧本,别人也能够拿过来就演,也能够改完再演,也能够改完变成新剧本,说到这里,感受docker跟github的思想很是相近。github

    不得不说linux下的docker安装真是轻松+写意,而windows下的docker安装简直就是灾难!虽然官方出了toolbox等一系列工具,作了不少兼容工做,但仍是会偶尔出现一些问题(尤为是各类管理工具不能用),安装完docker后,我推荐使用docker管理工具DockerFly,做者helyho是个很不错的人哦。(实际上我是到都快整完了,才发现的。。。唉!早点发现能省多少事!)web

    个人项目是使用Django框架开发,现阶段暂时是Django + uwsgi + nginx  + mysql,根据一些好的建议,我使用了多容器部署,这样可使服务与数据分离,有极大的好处,但相对的,对于我这样的小白,就意味着要有更多的坑要踩。sql

    我按照这个教程来进行,但一开始就遇到麻烦,个人开发环境是使用conda管理的,其中一些conda找不到的包使用pip安装的,不得已就得本身在镜像中安装miniconda,可是在Dockerfile中安装miniconda真是坑多多,由于miniconda必需要经过sh脚本安装,它途中会各类乱七八糟地问你是否许可这个那个的,致使Docker build不能自动地运行下去,当时没有想到好的解决办法,只好去找miniconda的专门镜像,找到了continuumio/miniconda,但如今我知道,当时能够在运行容器中装好,而后从新生成新镜像。docker

    有了教程的帮助,我省了很多的力气,因而我在Dockerfile中乱写一气,把本该用bash脚本写的用来“临场指挥”的一些命令也全都用 RUN 写到了Dockerfile中,使得Dockerfile成了一锅杂烩,直到后来,我才知道,Dockerfile中有下面的东西,让你“临场指挥”用,例如启动nginx。数据库

ENTRYPOINT [ "/usr/src/run.sh"]

CMD [ "/bin/bash" ]

    个人web容器要与mysql容器连通,才能让web操做数据库的数据,但即使在教程的帮助下,我依然没法将这两个牵到一块儿,像这样的代码django

docker run --name mysql \
-p 3309:3306 \
-d daocloud.io/mysql:5.6.30 \

-p是将mysql的端口映射到本地,我觉得让web程序访问3309的端口,就能链接到数据库,但事实是死活不通,我变换了各类接口,发现172.17.0.×是通的,原来那是docker容器的ip,顿时感受找到但愿和光明,但随即又想到,这是根据容器顺序配给的,mysql容器若是中止重启了,ip改变,难道还要去改程序不成?通过一连串的百度与论坛咨询,(开源中国回答个人技术问题的人实在不算多,也许是太low了),我才知道,我想要的,在docker中叫作容器互联,在个人代码中

docker run --name django \
--link mysql:mysql \
-p 2000:8000 \
-d mine/django-app \

--link就是干这个用的,host就是mysql,而-p映射的端口是给你在本地链接查看用的,不能用做容器互联。

    web容器终于运行起来了,但奇怪的是,容器运行不过几秒就自动退出,这令我倍感惊讶,百度后发现,docker的机制是这样的,docker容器是进程的容器,一个容器里能够运行多个进程,但最后一个运行的进程不能退出,不然进程退出后,容器也就退出了。在容器启动运行run.sh,进程的缺省设置是后台运行,这样致使run.sh运行结束,容器跟着run.sh退出而退出。所以,在run.sh中,最后的进程应强制采用前台运行,例如crond -f。这样run.sh就不会退出, docker run -d 运行时就能够保持容器后台运行。还有同志建议写个死循环

$ sudo docker run -d ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"

不过,我以为不太好,我采用了tail -f ×××.log。   

    最后应该将web落到nginx上了,但nginx要定位static静态文件,但我又不肯意将static目录从web中抽出,放到nginx中(这样是否是好的?若是读者感受很差,请在评论中指出),怎么好呢,docker的数据卷及时救援了我,docker的数据卷能够有效地解决多容器共享目录的问题,而且数据卷的更新,不会影响到容器,使用-v标记建立数据卷挂载到容器里,也能够挂载一个本地目录到容器,因而我

docker run --name django \
-v /usr/src/backend \
-v /usr/src/backend/static \
-d mine/django-app \

而nginx则使用 --volumes-from django 从而能够访问到静态文件与web目录。

通过这一周的踩坑,我对docker有了初步的了解,有很多心得体会,也还有好多不足,要学习一项新的技术,果真要走很多弯路,docker虚拟化技术的前途,可见其光明。

相关文章
相关标签/搜索