Docker部署笔记

 提示:转载请注明原文链接

 本文永久链接:https://360us.net/article/51.html

之前不一小心把Ubuntu16.10所有软件的apt-get配置给删了,然后就把系统给重新装了一遍。

想一下以后如果要再次重装系统的话,配置服务器这些有点繁琐,然后就想了下,web服务都用docker来运行。

docker基础用法,看起来还挺简单的,但是在我实际的使用中,按照自己的想法去部署服务的时候还是遇到了一些书上没说的细节问题。

这些细节问题,进行不下去时候,那么我先去搜索,搜索不到再去发帖,这样有时候会在一个小点上面卡主好几天。

看到这里,我当然都把这些问题一一解决了。

我这里的架构是Nginx+MySQL+PHP的。

一开始我是想用Dockerfile文件,把它们三个全都放到一个镜像里面取,一开始的Dockerfile内容如下:


FROM ubuntu:latest
RUN apt-get update
RUN apt-get install -y mysql-server nginx php-fpm php-mcrypt
EXPOSE 80 443
CMD ["/etc/init.d/nginx", "start"]


当我build的时候,遇到的第一个问题就是,安装MySQL的时候,会弹出一个要你输入root的对话框,等你输入之后按回车,然后就没有然后了,就一个光标再闪。

然后通过搜索,发现,Dockerfile在build的时候是不能交互的,那怎么办呢?

Ubuntu有个debconf工具,是可以预先把软件包需要交互输入的配置项的值给这个工具,然后这个工具会自动填入相应配置的值,这样就不会在安装的过程中询问你root秘密了。

这里还有个问题,这些配置项的变量名是什么呢?然后去看了下MySQL官方docker镜像的Dockerfile文件内容,用里面的配置项名称在Ubuntu系统里面是没有用的。

然后发现debconf-show命令可以查看软件包的预配置项,然后我执行命令debconf-show mysql-server,没有任何输出,一下子不知道怎么搞了。后面还是搜索到了配置项的名称,然后我的Dockerfile文件内容又变成的如下:


FROM ubuntu:latest
RUN apt-get update
RUN { \
        echo mysql-server mysql-server/root_password password root; \
        echo mysql-server mysql-server/root_password_again password root; \
    } | debconf-set-selections \
    &&  apt-get install -y mysql-server nginx php-fpm php-mcrypt
EXPOSE 80 443
CMD ["/etc/init.d/nginx", "start"]


上面的root就是我的MySQL root秘密。

然后我又build,这次要求你输入root秘密,顺利build出来了镜像。高兴死了,哈哈哈。。。

后面又想了想,还是MySQL独立一个镜像,Nginx+PHP一个镜像算了。

然后就是MySQL就是用的官方镜像运行的,这当然一切顺利,没有任何问题。

又修改了我的Dockerfile文件,内容如下:

FROM ubuntu:latest
RUN apt-get -qq update
RUN apt-get install -qqy nginx php-fpm php-mcrypt
RUN rm -rf /var/lib/apt/lists/*
EXPOSE 80 443
CMD ["/etc/init.d/nginx", "start"]

上面那个rm命令是参照了MySQL的官方镜像写的,是清理apt的垃圾用的。

build也没有问题,然后到运行了,run的命令如下:

sudo docker run --name web-server --link db-mysql:mysql -v /mnt/data/web/htdocs -v /mnt/data/web/nginx.conf.d:/etc/nginx -p 80:80 -p 443:443 -d nginx-php:latest

看看我的run命令,从前往后介绍。容器我命名位web-server,需要链接到MySQL容器,然后是我挂载了一个本地目录到容器里面,用来放web程序的文件,然后又挂在了一个本地目录到容器里面Nginx的配置根目录,我的目的是想在主机修改保存Nginx的配置,后面两个p是绑定主机的80和443端口到容器的对应端口,-d是后台运行容器,最后是要运行那个镜像。

run之后,我用docker ps指令看了下,不是运行状态,是exit的。

看到容器是停止运行的,那我就start一下:

admin@ubuntu:/mnt/data/web$ sudo docker start -a -i web-server
cat: /etc/nginx/nginx.conf: No such file or directory
 * Starting nginx nginx
   ...fail!

看最后启动失败了,这我又不知道怎么回事了。

然后我又用exec命令:

admin@ubuntu:/mnt/data/web$ sudo docker exec web-server -i -t /bin/bash
rpc error: code = 13 desc = invalid header field value "oci runtime error: exec failed: container_linux.go:247: starting container process caused \"exec: \\\"-i\\\": executable file not found in $PATH\"\n"

这个命令其实是针对已经晕了的容器的,而我的容器是停止的。

回到上面那个start失败,这个问题,我是去发帖求助的。

后面从回复的答案中了解到,挂载一个空目录到容器里面,是会请款容器对应目录的内容的。其实一开始,我一直认为是,如果主机容器有相同文件会主机的覆盖容器的,文件不同的话都会保留。

后面start失败就是因为我在run ngix-php镜像的时候,把容器里面Nginx的配置目录全给清空了。

然后我删除容器,重新run:

sudo docker run --name web-server --link db-mysql:mysql -v /mnt/data/web/htdocs -v /mnt/data/web/nginx.conf.d/site.conf:/etc/nginx/conf.d/site.conf -p 80:80 -p 443:443 -d nginx-php:latest

看,我改成挂载一个配置文件了。

之后再运行镜像,再docker ps。咦,怎么搞得,还是exit状态,都是成功的呀。

后面有了解到,docker容器是需要有程序一直在前台运行才不会退出的,而我上面Dockerfile的CMD名是什么?CMD ["/etc/init.d/nginx", "start"]。


运行这个命令开启的Nginx是运行在后台的,docker会认为你的容器已经没有程序在运行了,就会结束。

然后我去看了Nginx官方的Dockerfile内容。修改我的Dockerfile如下:

FROM ubuntu:latest
RUN apt-get update
RUN apt-get install -y nginx php-fpm php-mcrypt
RUN rm -rf /var/cache/apt/* \
    && rm -rf /var/lib/apt/lists/*
EXPOSE 80 443
RUN PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
CMD ["nginx", "-g", "daemon off;"]

最后CMD运行的命令是让Nginx在前台运行,不要后台运行,这样之后,成功访问到Nginx的默认页面,成功。。。

后面我就配置网站,改我本机的/mnt/data/web/nginx.conf.d/site.conf文件,改好之后,我进到容器去查看,空文件?莫名其妙呀。


这让我以为是不是不能挂载文件,只能挂载目录呢?

答案是,我用vim编辑了主机的文件,vim编辑文件会改变文件的inode,导致主机的的文件inode和容器里面对应文件的inode不一致,就是两个不同的文件了。

后面我就改用挂载目录了:/mnt/data/web/nginx.conf.d:/etc/nginx/conf.d。


至此,配置文件的文件也解决了。

我的想法不是Nginx+PHP在一个容器运行吗?

但是上面的Dockerfile创建的镜像,运行的容器默认是只会运行Nginx的,php的话是需要自己在进到容器终端,手动去运行PHP的,这样其实有有点麻烦的。

后面我就是想用一个shell脚本来统一运行Nginx和PHP。

Dockerfile改成这样:

FROM ubuntu:latest
RUN apt-get update
RUN apt-get install -y nginx php-fpm php-mcrypt php-curl php-gd php-mbstring php-mysql php-imagick vim
RUN rm -rf /var/cache/apt/* \
    && rm -rf /var/lib/apt/lists/*
COPY start-server.sh /opt/start-server.sh
RUN chmod +x /opt/start-server.sh
RUN PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
EXPOSE 80 443
CMD ["sh", "-c", "/opt/start-server.sh"]

我上面加那么多php扩展是,在使用过程中发现这些都需要额外安装的。

start-server.sh内容:

#!/bin/sh
/etc/init.d/php7.0-fpm start
nginx -g "daemon off;"

run命令:

sudo docker run -d -p 80:80 -p 443:443 -v /mnt/data/web/htdocs -v /mnt/data/web/nginx.conf.d:/etc/nginx/conf.d:ro --name web-server --link db-mysql:mysql nginx-php:latest

到这里一切都搞定了。。。不容易呀!


这里是凭回忆写的,中间会有忽略的地方。

 评论
暂无评论