基于Docker的Django-Mysql-Apache应用容器化

基于Docker的Django-Mysql-Apache应用容器化

2017-05-25

Mysql的容器

Django容器化

Apache容器

<span id = "1">

Mysql的容器

</span>

Mysql有官方发布的镜像,可以直接拉取,并按需求启动一个容器。

参考:这里

启动一个容器

docker run --name mysql-container -v /root/mysql_datadir:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql/mysql-server:5.7

启动一个5.7版本的Mysql容器,环境变量MYSQL_ROOT_PASSWORD表示superuser的密码,挂载宿主机的目录作为容器Mysql的数据存储目录。如果是第一次运行,Docker会发现本地没有Mysql镜像,会进行相应的依赖的拉取,随机启动容器。

docker_run_mysql
docker_run_mysql

docker ps -al

docker_ps_al
docker_ps_al

可以看出,mysql的容器依然暴露3306端口。

接入容器

docker exec -it mysql-container mysql -uroot -proot

access_mysql_docker
access_mysql_docker

成功接入mysql容器,创建成功。

查看Mysql的日志

容器的Mysql日志存储在/var/log/mysqld.log下

挂载宿主机目录作为Mysql的存储路径,并映射宿主机端口到容器外部端口

docker run --name mysql-container -p 3307:3306 -v /root/mysql_datadir:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql/mysql-server:5.7

将/root/mysql_datadir目录挂载进/var/lib/mysql作为数据库存储文件。映射宿主机3307端口到容器3306端口。容器启动后,mysql_datadir目录下会产生新文件

mysql_datadir
mysql_datadir

注意: 宿主机的目录必须要是绝对路径

当容器宕掉后,被清除后。重新启动一个Mysql容器,并挂载 mysql_datadir 作为数据库存储路劲时,记得忽略MYSQL_ROOT_PASSWORD环境变量的设置。先前存在的数据库文件不会有变化。

有时由于SElinux,读写目录会有冲突,敲入以下命令

chcon -Rt svirt_sandbox_file_t /root/mysql_datadir

进入容器配置数据库权限

docker exec -it mysql-container mysql -uroot -proot

grant all privileges on *.* to 'root'@'192.168.31.182' identified by 'root' with grant option;

从192.168.31.182可以访问这个容器的mysql服务

mysql -h[hostIP] -P3307 -uroot -p

 access_mysql_from_romote
access_mysql_from_romote

<span id="2">

Django容器化

</span>

从DockerHub上拉取Django镜像

docker pull library/Django:1.10.4-python3

需要等待一段时间

docker_pull
docker_pull

这个镜像已经配置好了python3.4和django1.10的环境。现在我们还要构建可以连接mysql的环境。

用Dockerfile文件构建一个镜像

新建一个Dockerfile文件,添加下面内容

Dockerfile_djanog
Dockerfile_djanog

build镜像

docker build -t [仓库和标签名称] [Dockerfile文件路径]

docker_build_django
docker_build_django
docker_image_django
docker_image_django

从镜像运行容器

docker run --name botmail --link mysql-container:db -v /root/docker_study/django_docker/botmail/:/var/www/ -p 8000:7000 -it 1015010127/botmail:v1 /bin/bash

启动一个名为botmail的容器,并且挂载代码文件到容器中,同时映射宿主机8000端口到容器的7000端口。连接MySQL的容器,并设置别名为db。

修改Django项目中的settings.py文件中的有关数据库连接的配置

docker_django_connect
docker_django_connect

注意: 同时要为当前容器的ip配置数据库权限,否则无法连接。

从镜像中启动django项目

docker exec -it botmail python manage.py runserver 0.0.0.0:7000
docker_run_django
docker_run_django

确保防火墙关闭后可以从外部访问。

这样构建的Django+mysql容器连接有一些问题,首先端口7000使用了硬编码,而且数据库连接使用‘db’硬编码,应当考虑使用docker-compose

使用docker-compose搭建MySQL+django

安装docker-compose,参考:官方安装文档

curl -L https://github.com/docker/compose/releases/download/$dockerComposeVersion/docker-compose-`uname -s\`-`uname -m` > /usr/local/bin/docker-compose

chmod +x /usr/local/bin/docker-compose

建立一个目录botmail_docker,并新建一个docker-compose.yml文件,写入以下内容。

  1 # docker-compose版本
  2 version: '3'
  3 # 服务
  4 services:
  5     # 数据库服务
  6     db:
  7         # 拉取镜像
  8         image: 1015010127/mysql-server:v2
  9         # 运行容器的名称
 10         container_name: mysql-container
 11         # 环境变量文件
 12         env_file: ./db.env
 13         # 端口映射,外部可以从3308端口访问
 14         ports:
 15             - "3308:3306"
 16         # 挂载目录
 17         volumes:
 18             # 数据储存目录,请自行定义
 19             - /root/docker_study/botmail_docker/data:/var/lib/mysql
 20         # 设置工作目录
 21         working_dir: /mysql_data_init
 22     # web服务
 23     web:
 24         image: 1015010127/botmail:v1
 25         container_name: botmail
 26         # 依赖db服务,先启动db再启动web
 27         depends_on:
 28             - db
 29         # 宕机即重启
 30         restart: always
 31         # 暴露端口
 32         ports:
 33             - "8000:7000"
 34         volumes:
 35             - ./botmail:/var/www/botmail   # 代码文件
 36         working_dir: /var/www/botmail
 37         # 启动容器是运行的命令
 38         command: python manage.py runserver 0:7000
 39         # 连接数据库
 40         links:
 41             - db

创建db.env文件用作设置db服务的环境变量。

  1 # 指定root的密码
  2 MYSQL_ROOT_PASSWORD=root
  3 # 创建一个新的数据库
  4 MYSQL_DATABASE=botmail_docker
  5 # 指定某个网段的ip可以访问
  6 MYSQL_ROOT_HOST=172.%.%.%
  7 # 要挂载的数据存储位置
  8 MYSQL_VOLUME_DATADIR=/root/docker_study/botmail_docker/data
  9 # 数据库初始化数据
 10 MYSQL_INIT_DIR=/root/docker_study/botmail_docker/mysql_init/botmail_online.sql
 11 # 运行时执行的
 12 EXEC_SQL=use botmail_docker;source data_init.sql;

创建data文件夹用作db服务的数据存储,通过以下命令启动容器组合。

docker-compose up

若是data文件夹中为空,db服务会进行一些初始化

docker-compose_up
docker-compose_up

启动成功后,通过docker-compose ps可以查看运行的容器,注意: 要在docker-compose.yml文件目录下敲命令。

docker-compose_ps
docker-compose_ps

现在可以从宿主机的ip访问botmail应用,但因为数据库中没有数据,需要初始化数据。

docker-compose exec db mysql -uroot -proot -e "use botmail_docker;source data_init.sql;"

data_init.sql文件已经存在在数据库容器的工作目录下。

docker_init_db_data
docker_init_db_data

现在可以进行登录了。

<span id="3">

Apache容器

</span>

拉取centos镜像,用来搭建apache服务

pull_centos
pull_centos

启动一个容器,并用yum安装httpd服务

run_centos
run_centos
yum_install_httpd
yum_install_httpd

启动httpd服务报错

apache_docker_start_error
apache_docker_start_error

这个问题可以参考后面的错误解决办法

此时先不管这个问题

安装django环境

安装python3

请参考源码包安装python3以及pip

pip安装django1.10以及pymysql

pip_install_django_pymysql
pip_install_django_pymysql

配置apache的python模块

安装mod_wsgi

wsgi全称为web server gateway interface,是web应用与服务器的接口模块,apache必须安装mod_wsgi才能够和python代码进行交互,之前有个版本用的是mod_python,现已经淘汰了

下载源码包

wget https://github.com/GrahamDumpleton/mod_wsgi/archive/4.5.15.tar.gz

解压并编译安装

解压并安装,注意提前安装gcc和httpd-devel,这是编译所必须的依赖包,否则编译报错(apx:commmand not found)

yum install gcc httpd-devel -y

编译安装mod_wsgi,注意指定python3的环境

compile_mod_wsgi_python3
compile_mod_wsgi_python3

成功编译安装的结果

success_complie_mod_wsgi
success_complie_mod_wsgi

说明模块已经安装到这个目录下了/usr/lib64/httpd/modules/mod_wsgi.so

在httpd的模块目录中可以找到

got_mod_wsgi_module
got_mod_wsgi_module

卸载依赖包,减小容器的体积

测试apache服务

刚刚遇到了apache服务无法启动的问题,现在进行解决

退出容器,将当前容器打包成镜像

docker commit -pm "新版apache_django配置" apache 1015010127/centos:apache_v4

最后一个选项是我的docker仓库名,可以自行定义

用以下新命令运行

docker run --privileged -d --name apache -p 6003:80 1015010127/centos:apache_v4 /usr/sbin/init

new_run_apache_docker
new_run_apache_docker

进入容器,启动apache服务

success_start_apache
success_start_apache

通过浏览器可以访问

browe_apache_welcome
browe_apache_welcome

6003端口是宿主机的,映射到容器的80端口

修改httpd.conf文件

添加以下两行

导入wsgi模块

LoadModule wsgi_module modules/mod_wsgi.so

django项目路径

WSGIPythonPath /var/www/botmail

python3的安装路径

WSGIPythonHome /usr/python3.5

配置虚拟主机

在/etc/httpd/conf.d/目录下新建一个文件botmail.conf,添加以下内容

<VirtualHost *:80>
WSGIScriptAlias / /var/www/botmail/botmail/wsgi.py
#WSGIPythonPath /var/www/botmail
#WSGIPythonHome /usr/python3.5
Alias /media/ /var/www/botmail/media/
Alias /static/ /var/www/botmail/html/dist/static/

<Directory /var/www/botmail/media>
Require all granted
</Directory>

<Directory /var/www/botmail/html/dist/static/>
Require all granted
</Directory>

<Directory /var/www/botmail/botmail>
<Files wsgi.py>
Require all granted
</Files>
</Directory>

</VirtualHost>

注意: 不要在虚拟主机的配置文件中配置WSGIPythonPath和WSGIPythonHome,否则启动apachectl服务时报错

因为是第一次接触apache服务器,这里的配置具体含义我不是特别清楚,有兴趣应该查阅官方文档。

重新启动apache服务,没错误的话就ok

apachectl restart

重新将这个容器打包一份镜像

现在就剩最后一步了:挂载botmail的项目路径

通过docker-compose.yml文件构建容器组合

创建一个docker-compose.yml文件,填入以下内容

# docker-compose版本
version: '3'
# 服务
services:
    # 数据库服务
    db:
        # 拉取镜像
        image: 1015010127/mysql-server:v2
        # 运行容器的名称
        container_name: mysql-container
        # 环境变量文件
        env_file: ./db.env
        # 端口映射,外部可以从3308端口访问
        ports:
            - "3308:3306"
        # 挂载目录
        volumes:
            # 数据储存目录,请自行定义
            - /root/docker_study/botmail_docker/data:/var/lib/mysql
        # 设置工作目录
        working_dir: /mysql_data_init
    # web服务
    web:
        image: 1015010127/centos:apache_v5
        container_name: botmail_apache
        # 依赖db服务,先启动db再启动web
        depends_on:
            - db
        # 宕机即重启
        restart: always
        # 暴露端口
        ports:
            - "8000:7000"
            - "6001:80"
        volumes:
            - /root/docker_study/botmail_docker/botmail:/var/www/botmail
        working_dir: /var/www/botmail
        
        command: /usr/sbin/init

        privileged: true
        # 连接数据库
        links:
            - db

在这个文件的目录下运行以下命令

docker-compose up

docker-compose_run_apache_mysql
docker-compose_run_apache_mysql

在浏览器上访问6001端口,即可看到你的django项目

web_docker_botmail
web_docker_botmail

可能会遇到的错误

apache配置错误

<span id=4>

1. 在centos7镜像中安装httpd服务,启动报错

</span>

centos_docker_httpd_error
centos_docker_httpd_error

打包当前容器,成镜像,然后从新用以下命令运行

docker run --privileged -d --name apache -p 6003:80 1015010127/centos:apache_v4 /usr/sbin/init

new_run_apache_docker
new_run_apache_docker

进入容器,启动apache服务

success_start_apache
success_start_apache

通过浏览器可以访问

browe_apache_welcome
browe_apache_welcome

6003端口是宿主机的,映射到容器的80端口

之后进入容器内启动apache可以成功

2. apache的python环境配置错误

因为python项目是用python3写的,我们都知道python3和python2是不兼容的,如果apache的是python2环境,如下,启动时通过查看/var/log/httpd/error_log日志可以查看apache启动的配置信息

python_2.7.5_configure
python_2.7.5_configure

访问web应用时,后端的python代码报错

python_run_2.7.5_error
python_run_2.7.5_error

python2的模块和python3并不兼容

在httpd/conf/httpd.conf添加Python3的安装目录,来指定使用python3的环境

add_python3_home
add_python3_home

但是在运行的时候却出现没有site模块的错误:ImportError: No module named site

python3_no_module_site
python3_no_module_site

现在查看wsgi是否配置正确,/etc/httpd/modules/mod_wsgi模块的依赖

ldd mod_wsgi.so

mod_wsgi_python2
mod_wsgi_python2

依赖的python竟然是python2,因此考虑利用python3环境编译mod_wsgi模块

下载源码包

wget https://github.com/GrahamDumpleton/mod_wsgi/archive/4.5.15.tar.gz

解压并安装,注意体检安装gcc和httpd-devel,这是编译所必须的依赖包,否则编译报错

yum install gcc httpd-devel -y

编译安装mod_wsgi,注意指定python3的环境

compile_mod_wsgi_python3
compile_mod_wsgi_python3

发生错误:relocation R_X86_64_32S against `_Py_NotImplementedStruct' can not be used when making a shared object; recompile with -fPIC

/usr/python3.5/lib/libpython3.5m.a: error adding symbols: Bad value

collect2: error: ld returned 1 exit status

apxs:Error: Command failed with rc=65536

make: *** [src/server/mod_wsgi.la] Error 1

这个错误的解决办法是要重新编译python3的源码,并加上--enable-shared选项

./configure --prefix=[python3的目录] --enable-shared

可能重新编译python后,运行python3的交互命令是,发生以下错误,依赖发生问题

python_lib_cannot_find
python_lib_cannot_find

通过复制python3目录下lib/libpython3.5m.so.1.0到/lib64/libpython3.5m.so.1.0可以解决

此时,可以正常编译mod_wsgi,且httpd/module/mod_wsgi.so依赖如下

mod_wsgi_python3
mod_wsgi_python3

注意: 重新编译了python源码,可能会造成扩展模块的丢失,注意重新用pip安装

python -m pip install [扩展模块名称]==[版本]

web界面显示Not Found

Not Found

The requested URL / was not found on this server.

not_found_error
not_found_error

可能是django的项目路径没有配置对

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容