本章会展示两种创建镜像的过程,其中一些操作比较简单的镜像使用Dockerfile来创建,而像Weblogic这样复杂的应用,则使用commit方式来创建,读者可根据自己的需求进行选择。
通过本章的介绍,用户操作可以根据自己需求轻松定制Web服务或应用镜像。
11.2 Apache
Apache 是一个高稳定性的、商业级别的开源Web服务器。目前Apache已经是巨世界使用排名第一的Web服务器软件。由于其良好的跨平台和安全性。Apache被广泛应用在多种平台和操作系统上。作为Apache软件基金会支持的项目,这的开发者社区完善而高效。自1995年发布至今,一直以高标准进行维护与开发。Apache名 称源自美国西南部一个印第安人部落:阿帕奇族,它支持类UNIX和Window系统。
编写Dockerfile文件,内容如下:
FROM httpd:2.4
COPY ./public-html /usr/local/apache2/htdocs/
创建项目目录public-html,并在此目录下创建index.html文件:
Hello,Docker!
构建自定义镜像:
[root@localhost ~]# docker build -t apache2-image .
构建完成后,使用docker run指令运行镜像:
[root@localhost ~]# docker run -it --rm --name apahce-container -p 80:80 apache2-image
通过本地的80端口即可访问静态页面,如图11-1所示。
图11-1 Apache 运行界面
也可以不创建自定义镜像,直接通过映射目录方式运行Apache容器:
[root@localhost ~]# docker run -it --rm --name my-apache -p 8080:80 -v "$PWD"/public-html:/usr/local/apache2/htdocs httpd:2.4
2.使用自定义镜像
首先,创建一个apache_ubuntu工作目录,在其中创建Dockerfile文件、run.sh文件和sample目录:
[root@localhost ~]# mkdir apache_ubuntu && cd apache_ubuntu
[root@localhost apache_ubuntu]# touch Dockerfile run.sh
下面是Dockerfile的内容和各个部分的说明:
#设置继承用户创建的sshd镜像
FROM sshd:dockerfile
#创建者基本信息
MAINTAINER [email protected]
#设置环境变量,所有操作都是非交互的
ENV DEBIAN_FRONTEND noninteractive
#安装
RUN apt-get -yq install apache2 && \
rm -rf /var/lib/apt/lists/*
#注意这里要更改系统的时区设置,因为在web应用中经常会用到时区这个系统变量,默认的ubuntu会让你的应用程序发生不可思议的后果
RUN echo "Asia/Shanghai" > /etc/timezone && \
dpkg-reconfigure -f noninteractive tzdata
#添加用户脚本,并设置权限,这会覆盖之前在这个位置的脚本
ADD run.sh /run.sh
RUN chmod 755 /*.sh
#添加一个示例的web站点,删掉默认安装在apahce文件下面文件,并将应用添加到示例中,用软链接到/var/www/html目录下面
RUN mkdir -p /var/lock/apache2 && mkdir -p /app && rm -rf /var/www/html && ln -s /app /var/www/html
COPY sample/ /app
#设置apache相关的一些变量,在容器启动的时候可以使用-e参数替代
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2
ENV APACHE_PID_FILE /var/run/apache2.pid
ENV APACHE_RUN_DIR /var/run/apache2
ENV APACHE_LOCK_DIR /var/lock/apache2
ENV APACHE_SERVERADMIN admin@localhost
ENV APACHE_SERVERNAME localhost
ENV APACHE_SERVERALIAS docker.localhost
ENV APACHE_DOCUMENTROOT /var/www
EXPOSE 80
WORKDIR /app
CMD ["run.sh"]
此sample站点的内容为输出Hello Docker!。然后在sample目录下创建inde.html,内容如下:
Hello,Docker!
run.sh脚本内容也很简单,只是启动apache服务
#!/bin/bash
exec apache2 -D FOREGROUND
此时,apache_ubuntu目录下面的文件结构为:
[root@localhost apache_ubuntu]# tree .
.
├── Dockerfile
├── index.html
├── run.sh
└── sample
1 directory, 3 files
下面,创建apache_ubuntu镜像:
#docker build -t apahce:ubuntu .
下面开始使用docker run指令测试镜像。可以使用-P参数映射需要开放的端口(22和80端口):
[root@localhost apache_ubuntu]# docker run -d -P apache:ubuntu
80f0b3f9d01bda0b96c019bee6a48b627a45979b3d26b8b840e1eaf38d72dd43
[root@localhost apache_ubuntu]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
80f0b3f9d01b apache:ubuntu "/run.sh" 7 seconds ago Up 4 seconds 0.0.0.0:32771->22/tcp, 0.0.0.0:32770->80/tcp stupefied_bose
在本地上使用curl抓取网页来验证刚才创建的sample站点
[root@localhost apache_ubuntu]# curl 127.0.0.1:32770
Hello,Docker!
读者也可以在其他设备上通过访问宿主主机ip:32770来访问sample站点。
不知道有没有细心的读者发现,在apache镜像的Dockerfile中只用EXPOSE定义了对外开放的80端口,而在docker ps -a命令的返回中,却看到新启动的内容映射了两个端口:22和80。
但是实际上,当尝试使用SSH登录到容器时,会发现无法登录。这是因为在run.sh脚本中并未启动SSH服务。这说明在使用Dockerfile创建镜像时,会继承父镜像的开放端口,但却不会继承启动命令。因此,需要在run.sh脚本中添加启动sshd的服务
命令
#!/bin/bash
/usr/bin/sshd & exec apache2 -D FOREGROUND
再次创建镜像:
[root@localhost apache_ubuntu]# docker build -t apache:ubuntu .
这次创建的镜像,将默认会同时启动SSH和Apache服务。
下面,来看看如何映射本地目录。可以通过映射本地目录的方式,来指定容器内Apache服务响应的内容,例如映射本地主机上当前目录下的www目录到容器的/var/www目录:
[root@localhost ~]# docker run -i -d -P -e APACHE_SERVERNAME=test -v `pwd`/www:/var/www/html apache:ubuntu
在当前目录内创建 www目录,并放上定义的页面index.html,内容如下:
HI,DOcker
This is the first day I meet the new world
Huw are you?
在本地主机上可访问测试容器提供的Web服务,查看获取内容为新配置的index.html页面信息。
11.2 Nginx
1.使用官方镜像
用户可以使用docker run指令直接运行官方Nginx镜像 :
[root@localhost ~]# docker run -d -p 80:80 --name webserver nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
f2aa67a397c4: Pull complete
3c091c23e29d: Pull complete
4a99993b8636: Pull complete
Digest: sha256:0fb320e2a1b1620b4905facb3447e3d84ad36da0b2c8aa8fe3a5a81d1187b884
Status: Downloaded newer image for nginx:latest
54214f78667d8f9a197de3244cb698329ef673ebd050ce0bced39f917602869f
然后使用docker ps指令查看当前运行的docker ps 指令查看当前运行的内容:
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
54214f78667d nginx "nginx -g 'daemon of…" About a minute ago Up About a minute 0.0.0.0:80->80/tcp webserver
目前,Nginx容器已经在0.0.0.80启动,并映射了80端口,此时可以打开浏览器访问此地址,就可以看到Nginx输出的页面,如图11-2所示:
图11-2 访问Nginx服务
2.自定义Web界面
同样的,创建index.html文件,并将index.html文件挂载至容器中,即可看到显示自定义的页面。
[root@localhost ~]# docker run -i -d -P -v `pwd`/www:/usr/share/nginx/html nginx
另外,也可以使用Dockerfile来构建新镜像。Dockerfile内容如下:
FROM nginx
COPY ./index.html /usr/share/nignx/html
[root@localhost nginx_dockerfile]# docker search tomcat | wc -l
26
开始构建镜像my-nginx:
[root@localhost nginx_dockerfile]# docker build -t my-nginx .
构建成功后执行docker run指令:
[root@localhost nginx_dockerfile]# docker run --name nginx-container -d my-nginx
11.3 Tomcat
Tomcat是由Apache软件基金会下属的Jakarta项目开发的一个Servlet容器,按照Sun Mircosystems提供的技术规范,实现了对Servlet和Java Server Page(JSP)的支持。同时,它提供了作为Web服务器的一些特有功能,如Tomcat管理和控制平台、安全域管理和Tomcat阀等。由于Tomcat本身也内含了一个HTTP服务器,也可以当作一个单独的Web服务器来使用。下面介绍如何定制Tomcat镜像。
首先,尝试的Docker Hubh 搜索已有的Tomcat相关镜像的个数:
[root@localhost nginx_dockerfile]# docker search tomcat | wc -l
26
下面能Tomcat 8.0 为例介绍定制Tomcat镜像的步骤。
1.准备工作
创建tomcat_ubuntu文件夹,从www.oracle.com网站上下载sun_jdk 1.8压缩包,下载tomcat压缩包
[root@localhost tomcat_ubuntu]# ll
总用量 195788
-rw-r--r--. 1 root root 9552281 4月 28 04:47 apache-tomcat-8.5.31.tar.gz
-rw-r--r--. 1 root root 727 5月 19 12:24 Dockerfile
-rw-r--r--. 1 root root 190921804 3月 30 03:45 jdk-8u172-linux-x64.tar.gz
创建Dockerfile
FROM ubuntu:14.04
MAINTAINER tjjingpan
# now add java and tomcat support in the container
ADD apache-tomcat-8.5.31.tar.gz /usr/local/
ADD jdk-8u172-linux-x64.tar.gz /usr/local/
# configuration of java and tomcat ENV
ENV JAVA_HOME /usr/local/jdk1.8.0_172
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.31
ENV CATALINA_BASE /usr/local/apache-tomcat-8.5.31
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
# container listener port
EXPOSE 8080
# startup web application services by self
CMD /usr/local/apache-tomcat-8.5.31/bin/catalina.sh run
创建docker镜像
docker build -t tjjingpan/tomcat-web .
docker run -P tjjingpan/tomcat-web:latest
[root@localhost tomcat_ubuntu]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
11a176f47455 tjjingpan/tomcat-web:latest "/bin/sh -c '/usr/lo…" 12 minutes ago Up 12 minutes 0.0.0.0:32805->8080/tcp epic_haibt
_____________________________________________________________________________________________________
原书生成方法
[root@localhost tomcat_ubuntu_1]# ls
apache-tomcat-8.5.31 create_tomcat_admin_user.sh Dockerfile jdk1.8.0_172 run.sh
Dockerfile文件
FROM registry.cn-hangzhou.aliyuncs.com/tjjingpan/ubuntu:14.04
MAINTAINER tjjingpan
#设置环境变量,所有操作都是非交互的
ENV DEBIAN_FRONTEND noninteractive
#注意这里要更改系统的时区设置
RUN echo "Asia/Shanghai" > /etc/timezone && \
dpkg-reconfigure -f noninteractive tzdata
#安装跟tomcat用户认证相关的软件
RUN apt-get install -yq --no-install-recommends wget pwgen ca-certificates && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# now add java and tomcat support in the container
#设置tomcat环境变量,若读者有其他的环境变量需要设置,也可以在这里添加。
ENV CATALINA_HOME /tomcat
ENV JAVA_HOME /jdk
#复制tomcat和jdk文件到镜像中
ADD apache-tomcat-8.5.31 /tomcat
ADD jdk1.8.0_172 /jdk
ADD create_tomcat_admin_user.sh /create_tomcat_admin_user.sh
ADD run.sh /run.sh
RUN chmod +x /*.sh
RUN chmod +x /tomcat/bin/*.sh
EXPOSE 8080
CMD ["/run.sh"]
create_tomcat_admin_user.sh文件
[root@localhost tomcat_ubuntu_1]# cat create_tomcat_admin_user.sh
#! /bin/bash
if [ -f /.tomcat_admin_created ]; then
echo "Tomcat 'admin' user already created"
exit 0
fi
#generate password
PASS=${TOMCAT_PASS:-$(pwgen -s 12 1)}
_word=$( [ ${TOMCAT_PASS} ] && echo "preset" || echo "random" )
echo "=> Creating and admin user with a ${_word} password in Tomcat"
sed -i -r 's/<\/tomcat-users>//' ${CATALINA_HOME}/conf/tomcat-users.xml
echo ' ' >> ${CATALINA_HOME}/conf/tomcat-users.xml
echo ' ' >> ${CATALINA_HOME}/conf/tomcat-users.xml
echo ' ' >> ${CATALINA_HOME}/conf/tomcat-users.xml
echo ' ' >> ${CATALINA_HOME}/conf/tomcat-users.xml
echo ' ' >> ${CATALINA_HOME}/conf/tomcat-users.xml
echo " " >> ${CATALINA_HOME}/conf/
tomcat-users.xml
echo '' >> ${CATALINA_HOME}/conf/tomcat-users.xml
echo "=> Done! "
touch /.tomcat_admin_created
echo "========================================================================"
echo "You can now configure to this Tomcat server using:"
echo ""
echo " admin:${PASS}"
echo ""
echo "========================================================================"
run.sh文件
[root@localhost tomcat_ubuntu_1]# cat run.sh
#!/bin/bash
if [ ! -f /.tomcat_admin_created ]; then
/create_tomcat_admin_user.sh
fi
/usr/sbin/sshd -D &
exec ${CATALINA_HOME}/bin/catalina.sh run
11.4 Jetty
Jetty是一个优秀的开源Servlet容器,以其高效,小巧,可嵌入式等优点深得人心,这为基于Java的Web内容(如JSP和Servlet)提供运行环境。Jetty基于Java语言编写,它的API以一组JAR包的形式发布,开发人员可以将Jetty容器实例化成一个对象,可以迅速为一些独立运行的Java应用提供Web服务。
相对于老牌的Tomcat,Jetty架构更合理,性能更优。尤其在启动速度上,主Tomcat望尘莫及。Jetty目前在国内外互联网企业中应用广泛。
DockerHub官方提供了Jetty镜像,直接运行docker run指令即可:
[root@localhost tomcat_ubuntu_1]# docker run -d -P jetty
[root@localhost tomcat_ubuntu_1]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a37e12a44150 jetty "/docker-entrypoint.…" 7 seconds ago Up 4 seconds 0.0.0.0:32846->8080/tcp wonderful_meitner
由于当前没有内容,会提示错误信息。
11.5 LAMP
可以使用自定义Dockerfile或者Compose方式运行LAMP,同时社区提供十分成熟的linode/lamp和tutum/lamp镜像。下面介绍后两种方法。
1.使用linode/lamp镜像
首先,执行docker run 指令,直接运行镜像,并进入容器内bash shell:
[root@localhost tomcat_ubuntu_1]# docker run -it -p 80:80 linode/lamp /bin/bash
root@b14b7825762b:/#
在容器内部shell启动apache以及mysql服务:
root@b14b7825762b:/# service apache2 start
* Starting web server apache2 *
root@b14b7825762b:/# service mysql start
* Starting MySQL database server mysqld [ OK ]
* Checking for tables which need an upgrade, are corrupt or were
not closed cleanly.
此时镜像中apache、mysql服务已经启动,可使用docker ps 指令查看运行中的容器:
[root@localhost tomcat_ubuntu_1]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b14b7825762b linode/lamp "/bin/bash" 5 minutes ago Up 5 minutes 0.0.0.0:80->80/tcp awesome_neumann
[root@localhost tomcat_ubuntu_1]#
此时通过浏览器访问本地80端口即可看到默认页面.
2.使用tutum/lamp镜像
首先,执行docker run指令,直接运行镜像;
11.6 CMS
Wordpress和Ghost
1.使用官方镜像
下载官方镜像
[root@localhost ~]# docker pull wordpress
然后,就可以创建并运行一个wrodpress容器
[root@localhost ~]# docker run --name some-wordpress -d -p 80:80 wordpress
ghost
[root@localhost ~]# docker run --name ghost-container -P -d ghost
11.7 持续开发与管理
信息行业日新月异,如何响应不断变化需求,快速适应和保证软件的质量?持续集成(Continuous integration,CI)正是针对这类问题的一种开发实践,它倡导开发团队定期进行集成验证。集成通过自动化的构建来完成,包括自动编译、发布和测试,从而尽快地发现错误。CI所描述的软件开发是从原始需求识别到最终产品部署整个过程中,需求以小批量形式在团队的各个角色间顺畅流动,能够以较短地周期完成需求的小粒度频繁交付。整个过程中,需求分析、产品的用户体验和交互设计、开发、测试、运维等角色需要密切协作。
持续集成特点包括:从检出代码、编译构建、运行测试、结果记录、统计等都是自动完成的,减少人工干预。需要有持续集成系统的支持,包括代码托管机制支持,以及集成服务器等。
持续交付(Continuous delivery, CD)则是经典的敏捷软件开发方法的自然延伸,它强调产品在修改后到部署上线的流程要敏捷化、自动化。甚至一些较小的改变也要尽早的部署上线。这跟传统软件在较大版本更新后才上线的思想不同。
11.7.1 Jenkins
11.7.2 Gitlab
11.8
笔者认为:包括Web服务在内的中间件领域十分适合引入容器技术,原因如下:
中间件服务器是除数据库服务外的主要计算节点,很容易成为性能瓶颈,所以通常需要大批量部署,而Docker对于批量部署有着许多先天的优势。
中间件服务器结构清晰,在剥离了配置文件、日志、代码目录之后,容器几乎可以处于零增长状态,这使得容器的迁移和批量部署更加方便;
中间件服务器很容易实现集群,
在实践过程中,读者需要注意数据的持久化,对于程序代码、程序的资源目录、日志、数据库文件等需要 实时更新的数据一定要通过-v参数映射到宿主主机的目录中来,避免发生数据丢失和带来性能下降。