【参考】:实现lamp docker数据容器(mysql)与应用容器(apache+php)独立运行
参考了博主的几篇文章,mysql是直接pull的官方,Apache+php用dockerfile实现,以【docker容器CentOS+ssh】中的镜像为基础镜像
一、生成mysql容器
下载镜像
docker pull mysql
下载完成后查看镜像:
docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
mysql latest e206c8d4ffcf 4 days ago 324.3 MB
生成mysql容器
创建一个文件夹用于挂载数据库文件
mkdir /mysql_lamp
然后生成容器
docker run -d -p 33060:3306 -e mysqld -e MYSQL_ROOT_PASSWORD=test-e MYSQL_USER=test -e MYSQL_PASSWORD=test -e MYSQL_DATABASE=discuz -v /
mysql_lamp:/var/lib/mysql --name mysql_db mysql
命令详解:
1、mysqld,#启动mysql服务,必须
2、MYSQL_ROOT_PASSWORD,#设置mysql的root密码,必须
3、MYSQL_USER ,#添加用户,可选
4、MYSQL_PASSWORD,#为用户设置密码,可选
5、MYSQL_DATABASE,#设置生成容器时需要新建的数据库,可选
6、将宿主机的目录“/mysql_data”映射到容器的“/var/lib/mysql”目录,可选。这是因为默认情况下数据库的数据库文件和日志文件都会存放于容器的AUFS文件层,这不仅不使得容器变得越来越臃肿,不便于迁移、备份等管理,而且数据库的性能也会受到影响,因此建议挂载到宿主机的目录到容器内。
7、mysql:镜像名字
-d: 后台运行容器,并返回容器ID;
-i: 以交互模式运行容器,通常与 -t 同时使用;
-t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
-p:端口映射
--name:生成容器的名字
二. 生成APACHE+PHP容器
编写Dockerfile
Dockergile:
#name:test #use:test #date:2017-11-29 FROM centos_sshd:v1 MAINTAINER test test@163.com ###1 ENV HTTPD_SOURCE http://archive.apache.org/dist/httpd/httpd-2.4.17.tar.gz ENV PHP_SOURCE http://cn2.php.net/distributions/php-5.6.14.tar.gz ENV MYSQL_SOURCE https://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.38.tar.gz #WORKDIR /root/ ############apache RUN yum -y install wget gcc make apr-devel apr apr-util apr-util-devel pcre-devel perl epel-release ###2 RUN cd /usr/local/src && curl -fSL "$HTTPD_SOURCE" -o httpd-2.4.17.tar.gz && tar -zxvf httpd-2.4.17.tar.gz && cd httpd-2.4.17 && ./configure --prefix=/usr/local/apache2 --enable-mods-shared=most --enable-so && make && make install ###mysql,we need mysql modules When we compile our PHP and PHP modules to connect
###to the database, so we need to install them.we don't need to install and
###launch mysql, just decompress and copy it to /usrl/local/mysql RUN curl -fSL "$MYSQL_SOURCE" -o mysql-5.6.38.tar.gz && tar -zxvf mysql-5.6.38.tar.gz && mv ./mysql-5.6.38 /usr/local/mysql ############php RUN yum -y install bzip2-devel openssl-devel perl-devel libxml2-devel libjpeg libjpeg-devel libpng-devel freetype-devel libmcrypt-devel ###3 RUN curl -fSL "$PHP_SOURCE" -o php-5.6.14.tar.gz && tar -zxvf php-5.6.14.tar.gz && cd php-5.6.14 && ./configure --prefix=/usr/local/php --with-apxs2=/usr/local/apache2/bin/apxs --with-config-file-path=/usr/local/php/etc --with-mysql ###4 --with-libxml-dir --with-gd --with-jpeg-dir --with-png-dir --with-freetype-dir --with-iconv-dir --with-zlib-dir --with-bz2 --with-openssl --with-mcrypt --enable-soap --enable-gd-native-ttf --enable-mbstring --enable-sockets --enable-exif --disable-ipv6 --enable-mods-shared=most --enable-so && make && make install && cd .. && rm -r /usr/local/src/ /usr/local/php/ && sed -i ###5 -e '1,/<AddType application/x-gzip .gz .tgz>/{s/<AddType application/x-gzip .gz .tgz>/AddType application/x-gzip .gz .tgz AddType application/x-httpd-php .php/}' -e 's/<DirectoryIndex index.html>/DirectoryIndex index.html index.htm index.php/' -e 's/#ServerName www.example.com:80/ServerName localhost:80/g' /usr/local/apache2/conf/httpd.conf COPY httpd-foreground.sh /usr/local/sbin/ RUN chmod u+x /usr/local/sbin/httpd-foreground.sh EXPOSE 80 CMD ["/usr/local/sbin/httpd-foreground.sh"]
httpd-foreground.sh
#!/bin/bash set -e /usr/sbin/sshd & /usr/local/apache2/bin/httpd -D FOREGROUND
解释一下Dockerfile:
1. 这三个环境变量分别是下载APACHE,PHP,MYSQL,执行前先试试链接是否有效,也可以换成自己想要版本链接,如果浏览器能下载但是编译过程中这里报错了,检查一下虚拟机能不能联网。
2. 这个模块我最初是放在下面###3的地方安装的,但是报了一个错:
Error configuring php 5.6 configure: error: mcrypt.h not found. Please reinstall libmcrypt
网上解决方法有几种,我用的是:
yum install -y epel-release yum install -y libmcrypt-devel 两个不能一起安装,因为CentOs6默认的yum源没有 libmcrypt-devel这个包,只能借助epel的yum源,所以先安装epel,再安装libmcrypt
3. 编译PHP时需要用到mysql进行模块编译,同时在php模块连接数据库时也需要用到mysql相关的模块,所以需要安装mysql,由于我们的mysql数据服务在另外的容器中运行,因此,并不需要安装和启动mysql,只需要解压并复制到/usrl/local/mysql即可。
4. 博主文章中编译php用的参数是--with-mysql=/usr/local/mysql,但是我在运行中会报错,去掉路径后正常。
5. 这里是shell的sed命令,sed是stream editor的缩写,一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。
这一步实现的功能是:
vi /usr/local/apache2/conf/httpd.conf #找到: AddType application/x-gzip .gz .tgz #在该行下面添加: AddType application/x-httpd-php .php #找到: <IfModule dir_module> DirectoryIndex index.html </IfModule> #将该行改为: <IfModule dir_module> DirectoryIndex index.html index.htm index.php </IfModule> #找到: #ServerName www.example.com:80 #修改为: ServerName localhost:80
关于sed的分析:
具体事例:
#把每行的12换成34,如果没有g标记,则只有每行第一个12被替换 sed 's/12/34/g' #匹配到第一个12的行号,把第一行到这个行号之间的12换成34,简单说就是只替换第一个12,后面的不变 sed '1,/12/{s/12/34/}' #替换最后一个12为34 sed ':a;$!{N;ba};s/(.*)12/134/' file :a 创建一个labela N 将下一行读入到模式空间 $! 如果不是最后一行,ba跳转到label a处 步骤1-3(即:a;N;$!ba;)就是为了将file全部内容读到模式空间中 #精确匹配555,某一行是5556的话并不匹配,a是追加,即在555下一行写入555888 sed -i '/<555>/a555888' file #精确匹配第一个555,并把其替换为2行数据,第1行是666,第2行是4个空格然后888 sed -i '1,/<555>/{s/<555>/666 888/}' file
参数介绍:
[root@www ~]# sed [-nefr] [动作] 选项与参数: -n :使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN 的数据一般都会被列出到终端上。但如果加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者动作)才会被列出来。 -e :直接在命令列模式上进行 sed 的动作编辑; -f :直接将 sed 的动作写在一个文件内, -f filename 则可以运行 filename 内的 sed 动作; -r :sed 的动作支持的是延伸型正规表示法的语法。(默认是基础正规表示法语法) -i :直接修改读取的文件内容,而不是输出到终端。 动作说明: [n1[,n2]]function n1, n2 :不见得会存在,一般代表『选择进行动作的行数』,举例来说,如果我的动作是需要在 10 到 20 行之间进行的,则『 10,20[动作行为] 』 function: a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~ c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行! d :删除,因为是删除啊,所以 d 后面通常不接任何咚咚; i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行); p :列印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~ s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!例如 1,20s/old/new/g 就是啦!
生成Apache+php镜像:
docker build -t apache_php:v1 .
生成Apache+php容器:
docker run -d -p 10022:22 -p 8001:80 --name apache_php --link mysql_db:mysql_db -v /var/www/html:/usr/local/apache2/htdocs apache_php:v1
--link mysql_db:mysql_db # 连接名为“mysql_db”的容器,并将其别名命名为mysql_db。
查看新生成的容器
docker ps
如果没有,一般是没启动,如果docker start 容器ID 也无法启动的话,查看日志
docker logs 容器ID
正常启动后,查看是否能访问:
vim /var/www/html/test.php <?php phpinfo() ?>
输入IP:PORT 访问一下
最后下载一个CMS,能完整的测试整个环境是否正常。
官方centos有200M,以此为基础安装了ssh后镜像有400M,再以此为镜像只安装Apache是650M,而安装了Apache+php是1.5个G,不知道该怎样优化。
1. 重命名镜像
如把entel_zmc_images :latest指定为entel_zmc_images:zmc_base
#docker tag entel_zmc_images entel_zmc_images:zmc_base
重命名后的镜像和原来的镜像拥有一样的imageID,所以删除的时候不能用
docker rmi ID
#要用docker rmi 名字:tag,如
#entel_zmc_images:zmc_base
2. 进入运行中的容器
ssh -D
tomcat
那么这个时候,用户就无法直接进入到容器中去,docker attach 容器id 就会一直卡着。
因为此时容器运行的进程是ssh,而不是/bin/bash 也没有虚拟终端(-it)参数,所以是进入不到的,
那么这种情况下,该如何attach进去并进入到一个/bin/bash里呢?
#docker exec -it containerID /bin/bash
3. 查询容器IP
1. 使用命令
docker inspect 容器ID
2.过虑出 IPAddress
docker inspect 容器ID | grep IPAddress