运行的软件越来越复杂,环境配置问题所造成的麻烦层出不穷……为了解决这些问题,Docker无疑在这一方向上迈出了具有革新意义的一步。在一台服务器上同时运行一千个Docker容器,这已经成为现实。源自《Docker技术入门与实战》。
本文章不对docker的原理和使用做深入介绍,只介绍如何操作把一个web项目打包成一个docker镜像交付,如何服务和依赖的太多,我建议把他们拆分开一个个的docker容器,用docker-compose来处理。
我的项目是用python3.6.5写的,使用了 tornado 异步框架,celery 任务队列(rabbitmq做broker_url,redis做result_backend),redis做缓存,mysql持久化,用supervisor管理进程。还使用了其他的依赖,比如处理音频的librosa,ai常用的torch,opencv, numpy, dlib等等。
特别提醒:对于需要cuda和cudnn的支持,此处推荐使用现成的nvidia的docker镜像来处理!
下面是几个对你有帮助的网址,部分可能需要科学上网:
https://gitlab.com/nvidia/container-images/cuda/blob/master/doc/supported-tags.md https://gitlab.com/nvidia/container-images/cuda
https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/user-guide.html
注意:需先安装 nvidia-container-toolkit,并重启docker服务!否则会报错!
拉取docker镜像,使用下面类似的命令,以自己情况而定:
docker pull nvidia/cuda:10.0-cudnn7-devel-ubuntu16.04
然后使用该镜像启动一个容器,进入容器后先测试2个命令,nvidia-smi和nvcc -V是否可以使用,可以使用后再继续!
启动容器命令,类似下面:
docker run --gpus all -it --name mycuda -v /data:/data nvidia/cuda:10.0-cudnn7-devel-ubuntu16.04 /bin/bash
注意加上 --gpus all,对于要使用声卡的还要加上 --device /dev/snd!
在容器里,然后继续你的web服务部署,就像在虚拟机里操作一样。可以写个脚本!比如类似以下步骤:
1. 更换镜像源
2. 修改pip源
3. 安装系统的各个依赖库,比如: gcc,cmake, openssl, zlib, wget等等
4. 安装编译python, redis,nginx,rabbitmq, mysql,supervisor等
5. 写入nginx配置,supervisor配置文件, 配置数据库账号密码权限,数据库初始化等。
6. 安装requirements.txt里的库
7. python代码需要编译成.so文件,用来保护代码和加速运行效率。
8. supervisor启动服务,测试是否正确。
测试正常后,有个问题:启动docker时,自动启动各个服务?
我是写一个启动脚本start.sh放在容器内,这个脚本做什么事情?
至少需要做三件事:
1. 设置所需要的环境变量
2. 以后台方式启动服务,比如redis,mysql,nginx,rabbitmq,web服务等
3. 执行bash: /bin/bash
然后还需要做几个事情:
1. 把容器保存成镜像,类似以下命令:
docker commit -a "Wind" -m "web server" -p 容器id webserver:v1
执行完后,使用docker images可以看到一个镜像名为webserver,tag为v1的镜像。
2. 把镜像导出成文件 web_server_v1.tar,类似以下命令:
docker save -o web_server_v1.tar webserver:v1
导出的镜像怎么使用呢?
docker load < web_server_v1.tar
执行完后,使用docker images可以看到一个镜像名为webserver,tag为v1的镜像。
运行容器检测,比如start.sh放在容器的/var/www下:
docker run --gpus all --device /dev/snd -it -p 443:443 -d -v /data:/data --name server webserver:v1 /var/www/start.sh
进入后查看,redis,nginx,mysql,web服务等都已经启动了。
-p 是把宿主机的端口443映射到容器的443端口
-d 是后台运行容器
-v 是把宿主机的目录挂载到容器
自此,web项目交付ok。有不对的地方欢迎交流!