运行的软件越来越复杂,环境配置问题所造成的麻烦层出不穷……为了解决这些问题,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镜像来处理!

 

 

注意:需先安装 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 是把宿主机的目录挂载到容器