本文最后更新于 259 天前,其中的信息可能已经过时,如有错误请发送邮件到wuxianglongblog@163.com
docker镜像手动制作
一.手动制作单服务的nginx镜像
1.启动一个基础容器,此处我使用的是centos7镜像。
[root@docker201.oldboyedu.com ~]# docker container run -it -p 80:80 centos:7 /bin/bash
2.修改容器中的软件源
[root@e19bb4af59b9 /]# curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
[root@e19bb4af59b9 /]# curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
3.安装nginx服务并启动nginx服务
[root@e19bb4af59b9 /]# yum -y install nginx
[root@e19bb4af59b9 /]#
[root@e19bb4af59b9 /]# nginx
温馨提示:
如下图所示,我们无法访问到nginx服务的首页文件,因为index.html指向的目标文件并不存在哟~
4.修复nginx的首页文件
[root@e19bb4af59b9 /]# rm -f /usr/share/nginx/html/index.html
[root@e19bb4af59b9 /]#
[root@e19bb4af59b9 /]# echo "<h1>oldboyedu.com</h1>" > /usr/share/nginx/html/index.html
[root@e19bb4af59b9 /]#
温馨提示:
如下图所示,由于默认的index.html文件存在问题,因此需要我们手动处理一下,就可以正常访问服务啦~
5.退出容器
[root@e19bb4af59b9 /]# exit
温馨提示:
如下图所示,当我们退出容器后,则容器会跟随者退出了,这意味着在该容器中运行的nginx进程也跟随着退出程序了。
综上所述,那么正在运行的程序产生的socket文件以及pid文件可能依旧保留在容器内,并没有对其进行删除!
对于某些服务而言,如果pid文件存在的话,可能会对下一次启动服务造成影响,但对于咱们的案例来说并不会造成影响哟~
6.将退出的容器提交为镜像
[root@docker201.oldboyedu.com ~]# docker container commit e19bb4af59b9 oldboyedu_nginx:v1
温馨提示:
如下图所示,镜像创建成功后,我们可以使用"docker images"进行查看。
7.测试镜像的可用性
[root@docker201.oldboyedu.com ~]# docker container run -it -d -p 8888:80 oldboyedu_nginx:v1 nginx -g 'daemon off;'
温馨提示:
(1)上课的时候需要演示出不执行nginx -g 'daemon off;'的效果,这样学员体验度更加;
(2)如果启动咱们自己的镜像时不指定命令,则默认继承我们基于centos 7镜像的默认初始命令,即"/bin/bash";
(3)手动制作镜像时貌似无法修改镜像的初始化命令,我们必须学习后面基于自动制作镜像的方式来指定初始化命令。
二.手动制作多服务的nginx + sshd镜像
1.启用一个基础容器,建议使用上一步安装好的镜像
我们想要手动制作多服务的nginx + sshd镜像,目前有两种访问:
(1)基于centos7镜像,单独安装nginx和sshd服务;
(2)基于我们上一步安装好的镜像,然后单独安装sshd服务;
启动基础镜像:
[root@docker201.oldboyedu.com ~]# docker container run -it -p 8888:80 -p 9999:22 oldboyedu_nginx:v1 /bin/bash
温馨提示:
如下图所示,sshd的软件包名称为"openssh-server"。
2.安装sshd服务
[root@134453e5d289 /]# yum -y install openssh-server
温馨提示:
(1)如下图所示,要求咱们在启动sshd服务之前,得优先启动sshd服务;
(2)由于我们的容器镜像比较干净,因此无法直接使用systemctl命令来启动sshd服务,这意味着我们需要手动来启动服务,还好可以参考默认的启动脚本参数;
(3)在执行后续的步骤前,请先查看一下"/etc/ssh"目录下的文件。
3.安装依赖包
[root@134453e5d289 /]# yum -y install initscripts
4.生成主机的密钥对
[root@134453e5d289 /]# /usr/sbin/sshd-keygen
温馨提示:
执行此步骤之前,建议先查看一下"ll /etc/ssh/"
5.启动sshd服务
[root@134453e5d289 /]# /usr/sbin/sshd
6.修改容器的root密码
[root@134453e5d289 /]# echo "123456" | passwd --stdin root
7.在宿主机中验证容器的sshd服务是否可用
[root@docker201.oldboyedu.com ~]# ssh 172.17.0.2
温馨提示:
登录成功后,请在容器再次执行一次"ps -ef"这样能看到多出来一个"sshd: root@pts/1"和"-bash"的进程哟~
8.退出容器
[root@134453e5d289 /]# exit
9.把安装好的服务提交成镜像
[root@docker201.oldboyedu.com ~]# docker container commit 134453e5d289 centos7_nginx_sshd:v1
温馨提示:
提交成镜像后,请思考是否有给自己留坑,如果很自信,绝对没有问题,则请思考下一步的分析。
10.验证容器的启动,发现问题
[root@docker201.oldboyedu.com ~]# docker container run -d -p 8888:80 -p 9999:22 centos7_nginx_sshd:v1 nginx -g 'daemon off;'
[root@docker201.oldboyedu.com ~]# docker container run -d -p 18888:80 -p 19999:22 centos7_nginx_sshd:v1 /usr/sbin/sshd -D
温馨提示:
不难发现,我们在测试镜像的时候发现了问题,如下所示,我们无法做到同时启动两个服务。
11.解决无法同时启动两个服务的思路(建议两种思路都尝试一下!)
思路一:
如下图所示,我们可用编写一个脚本来帮咱们启动服务,但该脚本的最后启动的服务应该阻塞当前的容器,避免容器退出。
[root@0636ae97b332 /]# vi /oldboyedu_init.sh
[root@0636ae97b332 /]#
[root@0636ae97b332 /]# cat /oldboyedu_init.sh
#!/bin/bash
# 启动nginx服务,该服务无需阻塞,否则我们就无法启动sshd服务啦!
#nginx -g 'daemon off;'
nginx
# 启动sshd服务,但一定要阻塞当前终端,不能退出,否则容器也会退出,前面执行的命令我们无需阻塞住哟~
/usr/sbin/sshd -D
[root@0636ae97b332 /]#
思路二:
启动容器时指定命令为: /bin/sh -c "nginx;/usr/sbin/sshd -D"
温馨提示:
容器是不走开机启动流程的,因此不要妄想将其写在"rc.local"配置文件中哟~
12.退出容器,再次提交镜像
[root@docker201.oldboyedu.com ~]# docker container commit 0636ae97b332 centos7_nginx_sshd:v2
13.再次启动容器进行测试
[root@docker201.oldboyedu.com ~]# docker container run -d -p 172.200.1.201:8888:80 -p 172.200.1.201:9999:22 centos7_nginx_sshd:v2 /bin/bash -x /oldboyedu_init.sh
温馨提示:
(1)启动容器时调用咱们的脚本;
(2)可以使用logs查看容器的输出内容;
(3)如下图所示,启动容器后,请用宿主机的IP地址及端口进行访问;
14.后记
nginx和ssh双服务镜像启动脚本制作:
cat /oldboyedu-start-birds.sh
#!/bin/bash
# nginx -g "daemon off;"
nginx -g "daemon on;"
# init root password
if [ -n "$1" ]; then
echo $1 | passwd --stdin root
elif [ -n "$OLDBOYEDU_ADMIN" ]; then
echo $OLDBOYEDU_ADMIN | passwd --stdin root
else
echo 321 | passwd --stdin root
fi
# Background operation
/usr/sbin/sshd -D
三.手动制作可道云镜像
1.关于可道云
可道云可以同步备份您的相册或重要资源, 随时随地查看、编辑、分享云端文件,轻松实现移动办公。
官方地址:
https://kodcloud.com/
下载地址:
https://kodcloud.com/download/
2.可道云镜像文件的环境说明
我们可以基于上面生成的nginx和ssh的容器继续制作可道云镜像,但可道云是一个PHP项目,因此得在咱们的容器里安装响应的php程序。
本案例采用nginx 1.16,php 5.4版本即可。
3.启动基础容器
[root@docker201.oldboyedu.com ~]# docker container run -it centos7_nginx_sshd:v2 /bin/bash
温馨提示:
容器启动成功后,我们可以安装咱们的kod啦~
4.安装php依赖包
[root@b33f88c4edfd /]# yum -y install php-fpm php-mbstring.x86_64 php-gd
温馨提示:
安装php程序的依赖包。
5.修改nginx的配置文件
(1)创建代码存放目录
[root@b33f88c4edfd /]# mkdir -pv /oldboyedu/html # 创建存放代码的目录
mkdir: created directory ‘/oldboyedu’
mkdir: created directory ‘/oldboyedu/html’
[root@b33f88c4edfd /]#
[root@b33f88c4edfd /]# ll /oldboyedu/html/ -d
drwxr-xr-x 2 root root 6 Jun 14 17:29 /oldboyedu/html/
[root@b33f88c4edfd /]#
(2)修改nginx的配置文件
[root@b33f88c4edfd /]# egrep -v "^$|^*#" /etc/nginx/nginx.conf.default > /etc/nginx/nginx.conf
[root@b33f88c4edfd /]#
[root@b33f88c4edfd /]# vi /etc/nginx/nginx.conf
[root@b33f88c4edfd /]#
[root@b33f88c4edfd /]# cat /etc/nginx/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root /oldboyedu/html;
index index.php index.html index.htm;
}
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /oldboyedu/html$fastcgi_script_name;
include fastcgi_params;
}
}
}
[root@b33f88c4edfd /]#
(3)测试nginx的配置文件是否正确
[root@b33f88c4edfd /]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@b33f88c4edfd /]#
温习提示:
mkdir -pv /oldboyedu/code/{bird,kod,wordpress}
cat > /etc/nginx/conf.d/oldboyedu-bird.conf <<EOF
server {
listen 81;
root /oldboyedu/code/bird;
}
EOF
cat > /etc/nginx/conf.d/oldboyedu-kod.conf <<EOF
server {
listen 82;
root /oldboyedu/code/kod;
location / {
index index.php index.html index.htm;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
# 注意下使用echo指令时对于特殊符号要使用转义符哟~否则将不识别.
fastcgi_param SCRIPT_FILENAME /oldboyedu/code/kod\$fastcgi_script_name;
include fastcgi_params;
}
}
EOF
6.修改php程序的运行用户
[root@b33f88c4edfd /]# vi /etc/php-fpm.d/www.conf
温馨提示:
如下图所示,我们只需修改运行php的用户名和组名即可。
6.运行php程序
[root@b33f88c4edfd /]# php-fpm -D
7.解压代码
(1)将下载的kod软件包上传到容器中
[root@docker201.oldboyedu.com ~]# docker container cp kodexplorer4.40.zip b33f88c4edfd:/oldboyedu/html
(2)安装unzip程序包
[root@b33f88c4edfd /]# yum -y install unzip
(3)解压软件包
[root@b33f88c4edfd ~]# cd /oldboyedu/html
[root@b33f88c4edfd html]#
[root@b33f88c4edfd html]# unzip kodexplorer4.40.zip
(3)修改文件权限
[root@b33f88c4edfd html]# chown -R nginx:nginx .
8.编写启动脚本
[root@b33f88c4edfd html]# vi /oldboyedu_init.sh
[root@b33f88c4edfd html]#
[root@b33f88c4edfd html]#
[root@b33f88c4edfd html]# cat /oldboyedu_init.sh
#!/bin/bash
# 启动nginx服务,该服务无需阻塞,否则我们就无法启动sshd服务啦!
#nginx -g 'daemon off;'
nginx
# 启动php程序
php-fpm -D
# 启动sshd服务,但一定要阻塞当前终端,不能退出,否则容器也会退出,前面执行的命令我们无需阻塞住哟~
/usr/sbin/sshd -D
[root@b33f88c4edfd html]#
9.提交镜像
[root@docker201.oldboyedu.com ~]# docker container commit b33f88c4edfd oldboyedu_kod:v1
10.启动镜像
[root@docker201.oldboyedu.com ~]# docker container run -d -p 8888:80 oldboyedu_kod:v1 /bin/bash -x /oldboyedu_init.sh
温馨提示:
(1)我这里只需要访问80端口,因此我启动容器的时候就只暴露了80端口哟;
(2)访问宿主机的8888端口,就可以访问到容器的80端口了,可以访问如下图所示的界面,输入管理员密码即可;
11.登录可道云
如上图所示,用户默认是"admin",我们使用初始化指定的管理员密码进行登录。
登录成功后的界面如下图所示。
四.常见的报错汇总
1.Failed to get D-Bus connection: Operation not permitted
问题描述:
如下图所示,在启动sshd服务时,抛出了"Failed to get D-Bus connection: Operation not permitted"异常。
问题原因:
未运行"/usr/bin/dbus-daemon"进程。
解决方案:
方案一:
运行"/usr/bin/dbus-daemon"进程,但需要对其进行一定的了解。
方案二:
手动启动ssh服务。
2./usr/sbin/sshd-keygen: line 10: /etc/rc.d/init.d/functions: No such file or directory
问题描述:
手动运行"/usr/sbin/sshd-keygen"脚本时报错。
问题原因:
该脚本调用系统函数库"functions"。
解决方案:
yum provides /etc/rc.d/init.d/functions # 查看该文件被哪个依赖包产生。
yum -y install initscripts # 根据上一步结果得到该步骤。