CHAPTER 9 Web服务与应用(一)


Web服务和应用是目前互联网技术领域的热门技术。本章将重点介绍如何使用Docker来运行常见的Web服务器(包括Apache、Nginx、Tomcat等), 以及一些常用应用(包括LAMP和CI/CD),通过介绍具体的镜像构建方法与使用步骤展示容器的强大功能。

本章会展示两种创建镜像的过程。其中一些操作比较简单的镜像使用Dockerfile来创建,而像Weblogic这样复杂的应用,则使用commit方式来创建,读者可根据自己的需求进行选择。

通过本章的介绍,用户将可以根据自己需求轻松定制Web服务或应用镜像。

9.1 Apache

Apache是一个高稳定性的、商业级别的开源Web服务器,是目前世界使用排名第一的Web服务器软件。由于其良好的跨平台和安全性,Apache 被广泛应用在多种平台和操作系统上。Apache作为软件基金会支持的项目,其开发者社区完善而高效,自1995年发布至今,一直以高标准进行维护与开发。Apache音译为阿帕奇,源自美国西南部一个印第安人部落的名称(阿帕奇族)。

9.1.1 使用DockerHub镜像

Docker Hub官方提供的Apache镜像, 并不带PHP环境。 如果读者需要PHP环境支持,可以选择PHP镜像(https://registry.hub.docker.com/_/php/), 并请使用含-apache标签的镜像,如7.0.7-apache。如果仅需要使用Apache运行静态HTML文件, 则使用默认官方镜像即可。编写Dockerfile文件, 内容如下:

[root@dbc-server-554 apache]# cat dockerfile
FROM httpd:2.4
COPY ./index.html /usr/local/apache2/htdocs/
[root@dbc-server-554 apache]# cat index.html
<!DOCTYPE html>
<html>
 <body>
  <p>Hello,Docker!</p>
 </body>
</html>
[root@dbc-server-554 apache]# docker build -t my-apache-app .
Sending build context to Docker daemon  3.072kB
Step 1/2 : FROM httpd:2.4
 ---> dabbfbe0c57b
Step 2/2 : COPY ./index.html /usr/local/apache2/htdocs/
 ---> 5e1f1db65f03
Successfully built 5e1f1db65f03
Successfully tagged my-apache-app:latest
[root@dbc-server-554 apache]# docker run -d -p 80:80 my-apache-app
1a0006a0250212b85c792cd5a57cee01f0bed87ecdc8a5d73d634aea70b38c8b
[root@dbc-server-554 apache]# curl http://192.168.5.54:80
<!DOCTYPE html>
<html>
 <body>
  <p>Hello,Docker!</p>
 </body>
</html>

使用httpd镜像直接启动容器,效果一样

[root@dbc-server-554 apache]# docker run -d --rm --name my-apache-app -p 80:80 -v "$PWD":/usr/local/apache2/htdocs/ httpd:2.4
8f26c49cd731a5fc2a656e8d7d0513bcfdeb1441ab61f1cd1eab52291cf7041f
[root@dbc-server-554 apache]# docker ps
CONTAINER ID   IMAGE                 COMMAND                  CREATED             STATUS             PORTS                                         NAMES
8f26c49cd731   httpd:2.4             "httpd-foreground"       4 seconds ago       Up 2 seconds       0.0.0.0:80->80/tcp, :::80->80/tcp             my-apache-app
[root@dbc-server-554 apache]# curl http://192.168.5.54:80
<!DOCTYPE html>
<html>
 <body>
  <p>Hello,Docker!</p>
 </body>
</html>

9.1.2 使用自定义镜像

首先, 创建一个apache_ubuntu工作目录,在其中创建Dockerfile文件、run.sh文件和sample目录:

[root@dbc-server-554 docker]# mkdir apache_ubuntu;cd apache_ubuntu;touch Dockerfile run.sh;mkdir sample
[root@dbc-server-554 apache_ubuntu]# ll
total 0
-rw-r--r-- 1 root root 0 Jan 16 17:31 Dockerfile
-rw-r--r-- 1 root root 0 Jan 16 17:31 run.sh
drwxr-xr-x 2 root root 6 Jan 16 17:31 sample

下面是Dockerfile的内容和各个部分的说明:

[root@dbc-server-554 apache_ubuntu]# cat Dockerfile
FROM sshd:dockerfile
LABEL maintainer yurq
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get -yq install apache2 && rm -rf /var/lib/apt/lists/*
RUN apt-get update && apt-get -y install tzdata
RUN echo "Asia/Shanghai" >  /etc/timezone && rm -f /etc/localtime && dpkg-reconfigure -f noninteractive tzdata

ADD run.sh /run.sh
RUN chmod 755 /*.sh

RUN mkdir -p /var/lock/apache2 && mkdir -p /app && rm -rf /var/www/html && ln -s /app /var/www/html && mkdir /var/run/apache2
COPY sample/ /app

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"]

当前目录:

[root@dbc-server-554 apache_ubuntu]# ls -R
.:
Dockerfile  run.sh  sample

./sample:
index.html
[root@dbc-server-554 apache_ubuntu]# cat sample/index.html
<!DOCTYPE html>
<html>
 <body>
  <p>Hello,Docker!</p>
 </body>
</html>
[root@dbc-server-554 apache_ubuntu]# cat run.sh
#!/bin/bash
exec apache2 -D FOREGROUND

创建镜像:

[root@dbc-server-554 apache_ubuntu]# docker build -t apache:ubuntu .
Sending build context to Docker daemon   5.12kB
Step 1/23 : FROM sshd:dockerfile
 ---> cae337d9b3f7
 ...
Removing intermediate container 6a3ad540ce2d
 ---> 6121eb96d3ca
Successfully built 6121eb96d3ca
Successfully tagged apache:ubuntu

查看镜像并启动容器

[root@dbc-server-554 apache_ubuntu]# docker images
REPOSITORY                                          TAG              IMAGE ID       CREATED         SIZE
apache                                              ubuntu           6121eb96d3ca   14 hours ago    374MB
[root@dbc-server-554 apache_ubuntu]# docker run -d -P apache:ubuntu
074aef852cc140a1a29b5a0e7dae760a9cd9f4084a0dbb7c38ad32da1eddca0b
[root@dbc-server-554 apache_ubuntu]# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED         STATUS        PORTS                                                                              NAMES
074aef852cc1   apache:ubuntu       "/run.sh"                2 seconds ago   Up 1 second   0.0.0.0:32801->22/tcp, :::32801->22/tcp, 0.0.0.0:32800->80/tcp, :::32800->80/tcp   wizardly_elion
[root@dbc-server-554 apache_ubuntu]# curl 127.0.0.1:32800
<!DOCTYPE html>
<html>
 <body>
  <p>Hello,Docker!</p>
 </body>
</html>
[root@k8s-node-02 ~]# curl 192.168.5.54:32800
<!DOCTYPE html>
<html>
 <body>
  <p>Hello,Docker!</p>
 </body>
</html>

httpd+sshd
读者也可以在其他设备上通过访问宿主主机ip:32800来访问sample站点。
下面,用户看看Dockerfile创建的镜像拥有继承的特性。不知道有没有细心的读者发现,在apache镜像的Dockerfile中只用EXPOSE定义了对外开放的80端口, 而在docker ps -a命令的返回中,却看到新启动的容器映射了2个端口:22和80。

但是实际上,当尝试使用SSH登录到容器时,会发现无法登录。这是因为在run.sh 脚本中并未启动SSH服务。 这说明在使用Dockerfile创建镜像时,会继承父镜像的开放端口, 但却不会继承启动命令。因此, 需要在run.sh脚本中添加启动sshd的服务的命令:

[root@dbc-server-554 apache_ubuntu]# cat run.sh
#!/bin/bash
/usr/sbin/sshd &
exec apache2 -D FOREGROUND

再次创建镜像:

[root@dbc-server-554 apache_ubuntu]# docker build -t apache:ubuntu_0.1 .
Sending build context to Docker daemon   5.12kB
Step 1/23 : FROM sshd:dockerfile
 ---> cae337d9b3f7
...

这次创建的镜像,将默认会同时启动SSH和Apache服务。
下面, 用户看看如何映射本地目录。用户可以通过映射本地目录的方式,来指定容器内Apache服务响应的内容,例如映射本地主机上当前目录下的www目录到容器内的/var/www目录:

[root@dbc-server-554 apache_ubuntu]# docker run -i -d -p 80:80 -p 103:22 -e APACHE_SERVERNAME=test -v `pwd`/www:/var/www:ro apache:ubuntu_0.1
f6109bffeb3ea9026f52320b756c43892c88e87cd787997ff7c2d0ba212c01be
[root@dbc-server-554 apache_ubuntu]# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED         STATUS         PORTS                                                                              NAMES
f6109bffeb3e   apache:ubuntu_0.1   "/run.sh"                2 seconds ago   Up 2 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:103->22/tcp, :::103->22/tcp             heuristic_lewin

9.1.3 相关资料

Apache官网:https://httpd.apache.org/
Apache官方仓库:https://github.com/apache/httpd

9.2 Nginx

Nginx (发音为"engine-x")是一款功能强大的反向代理服务器, 支持HTTP、HTTPS、SMTP、POP3、IMAP等协议。它也可以作为负载均衡器、HTTP缓存或Web服务器。Nginx一开始就专注千高并发和高性能的应用场景。它使用类BSD开源协议,支持Linux、BSD、Mac、Solaris、AIX等类Unix系统, 同时也有Windows上的移植版本。
Nginx特性如下:

  • 热部署:采用master管理进程与worker工作进程的分离设计,支持热部署。在不间断服务的前提下,可以直接升级版本。也可以在不停止服务的情况下修改配置文件,更换日志文件等。
  • 高并发连接:Nginx可以轻松支持超过100K的并发, 理论上支持的并发连接上限取决于机器内存。
  • 低内存消耗:在一般的情况下,10K个非活跃的HTTPKeep-Alive连接在Nginx中仅消耗2.5MB的内存,这也是Nginx支持高并发连接的基础。
  • 响应快:在正常的情况下,单次请求会得到更快的响应。在高峰期,Nginx可以比其他的Web服务器更快地响应请求。
  • 可靠性:Nginx是一个高可靠性的Web服务器,这也是用户为什么选择Nginx的基本条件,现在很多的网站都在使用Nginx,足以说明Nginx的可靠性。高可靠性来自其核心框架代码的优秀设计和实现。

本节将首先介绍Nginx官方发行版本的镜像生成,然后介绍第三方发行版Tengine镜像的生成

9.2.1 使用DockerHub镜像

用户可以使用docker run指令直接运行官方Nginx镜像

[root@dbc-server-554 apache_ubuntu]# docker run -d -p 80:80 --name webservernginx nginx:1.12.0-apline
d5c1a3b12cdb236d448464ec4652b8b5ba1bb0b78e581410eef95bb24012e3e8
[root@dbc-server-554 apache_ubuntu]# docker ps
CONTAINER ID   IMAGE                 COMMAND                  CREATED         STATUS        PORTS                                         NAMES
d5c1a3b12cdb   nginx:1.12.0-apline   "nginx -g 'daemon of…"   2 seconds ago   Up 1 second   0.0.0.0:80->80/tcp, :::80->80/tcp             webservernginx
[root@dbc-server-554 apache_ubuntu]# curl 127.0.0.1
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        ...

9.2.2 自定义web页面

新建web页面文件index.html

[root@dbc-server-554 nginx]# cat index.html
<html>
        <title>text</title>
        <body>
                <div> hello world </div>
        </body>
</html>

启动镜像

[root@dbc-server-554 nginx]# docker run -d -p 80:80 -v `pwd`:/usr/share/nginx/html:ro nginx:latest
72ab822445fd32678981c31f52aa808c358149fbc3f7e0c2a0fff2f16efd20ff
[root@dbc-server-554 nginx]# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED         STATUS         PORTS                                         NAMES
72ab822445fd   nginx:latest        "/docker-entrypoint.…"   6 seconds ago   Up 4 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp             hardcore_bhabha
[root@dbc-server-554 nginx]# curl 127.0.0.1
<html>
        <title>text</title>
        <body>
                <div> hello world </div>
        </body>
</html>

使用dockerfile启动:

[root@dbc-server-554 nginx]# cat dockerfile
FROM nginx:latest
COPY ./index.html /usr/share/nginx/html/
[root@dbc-server-554 nginx]# docker build -t my-nginx .
Sending build context to Docker daemon  4.096kB
Step 1/2 : FROM nginx:latest
 ---> 605c77e624dd
Step 2/2 : COPY ./index.html /usr/share/nginx/html/
 ---> ef319a6d92c7
Successfully built ef319a6d92c7
Successfully tagged my-nginx:latest
[root@dbc-server-554 nginx]# docker run -d -p 80:80 ef3
adea8604e940265ef8c1cb9256df1216bec2190e67e95e97149e6ae873325137
[root@dbc-server-554 nginx]# curl 127.0.0.1
<html>
        <title>text</title>
        <body>
                <div> hello world </div>
        </body>
</html>

9.2.3 使用自定义Dockerfile

编写dockerfile:

[root@dbc-server-554 nginx]# cat dockerfile
#设置继承自创建的sshd镜像
FROM sshd:dockerfile
#下面是一些创建者的基本信息
MAINTAINER docker_user (user@docker.com)
#安装nginx,设置 nginx以非daemon方式启动。
RUN \
        apt-get install -y  nginx && \
        rm  -rf /var/lib/apt/lists/* &&  \
        echo "\ndaemon off;" >>  /etc/nginx/nginx.conf&& \
        chown -R  www-data:www-data /var/lib/nginx
RUN apt-get update && apt-get -y install tzdata
RUN echo "Asia/Shanghai" >  /etc/timezone&&  \
        dpkg-reconfigure -f  noninteractive tzdata
#注意这里要更改系统的时区设置,因为在Web应用中经常会用到时区这个系统变量,默认ubuntu的设置会让你的应用程序发生不可思议的效果哦

#添加用户的脚本,并设暨权限,这会覆盖之前放在这个位置的脚本
ADD run.sh /run.sh
RUN chmod 755 /*.sh

#定义可以被挂载的目录,分别是虚拟主机的挂载目录、证书目录、配置 目录、和日志目录
VOLUME ["/etc/nginx/sites-enabled", "/etc/nginx/certs","/etc/nginx/conf.d","/ var/log/nginx"]

#定义工作目录
WORKDIR /etc/nginx

#定义输出命令
CMD ["/run.sh"]

#定义输出端口
EXPOSE 80
EXPOSE 443
[root@dbc-server-554 nginx]# cat run.sh
#!/bin/bash
/usr/sbin/sshd &
/usr/sbin/nginx

构建启动镜像

[root@dbc-server-554 nginx]# docker build -t sshdnginx .
[root@dbc-server-554 nginx]# docker run -d -P sshdnginx
a05fa96e0ecf9385bf741a932b5cd06a4e04510fdbdbb926dba57b2858e7324b
[root@dbc-server-554 nginx]# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS          PORTS                                                                                                                         NAMES
a05fa96e0ecf   sshdnginx           "/run.sh"                6 seconds ago    Up 5 seconds    0.0.0.0:32804->22/tcp, :::32804->22/tcp, 0.0.0.0:32803->80/tcp, :::32803->80/tcp, 0.0.0.0:32802->443/tcp, :::32802->443/tcp   frosty_robinson
[root@dbc-server-554 nginx]# curl 127.0.0.1:32803
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
    ...

参数优化
为了能充分发挥Nginx的性能,用户可对系统内核参数做一些调整。下面是一份常见的适合运行Nginx服务器的内核优化参数:

net.ipv4.ip_forward=0 
net.ipv4.conf.default.rp_filter=  1 
net.ipv4.conf.default.accept_source_route= 0 
kernel.sysrq= 0 
kernel.core_uses_pid= 1 
net.ipv4.tcp_syncookies=1 
kernel.ms-nb=  65536 
kernel.ms-ax=  65536 
kernel.shmmax =  68719476736 
kernel.shmall=  4294967296 
net. ipv4.tcp_max_tw_buckets= 6000 
net. ipv4.tcp_sack= 1
 net.ipv4.tcp_window_scaling=1 
net.ipv4.tcp_rmem=  4096 87380 4194304 
net.ipv4.tcp_wmem= 4096 16384 4194304 
net.core.wmem_default=  8388608 
net.core.rmem_default= 8388608 
net.core.rmem_max=  16777216 
net.core.wmem max= 16777216 
net.core.netdev_max_backlog= 262144 
net.core.somaxconn =  262144 
net.ipv4.tcp_max_orphans =  3276800 
net.ipv4.tcp_max_syn_backlog=  262144 
net.ipv4.tcp_timestamps=  0 
net.ipv4.tcp_synack_retries=  1 
net.ipv4.tcp_syn_retries=  1 
net.ipv4.tcp_tw_recycle = 1 
net.ipv4.tcp_tw_reuse =  1 
net.ipv4.tcp_mem =  94500000 915000000 927000000 
net.ipv4.tcp_fin_timeout=1 
net.ipv4.tcp_keepalive_time=  30 
net.ipv4.ip_local_port_range=  1024 65000 

关于新版本的docker不支持挂载文件,只能挂载目录

[root@dbc-server-554 nginx]# docker run -d -P -v /root/docker/nginx/nginx/etc/sysctl.conf:/etc/sysctl.conf:ro sshdnginx
5cda29a9fc9c2fe81d1320fed2554934d084acdd816a5be39383cbfa693b6c13
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error mounting "/root/docker/nginx/nginx/etc/sysctl.conf" to rootfs at "/etc/sysctl.conf": mount /root/docker/nginx/nginx/etc/sysctl.conf:/etc/sysctl.conf (via /proc/self/fd/6), flags: 0x5001: not a directory: unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type.

当我们第一次执行失败后,删除目录sysctl.conf,然后手动创建文件sysctl.conf,然后再启动容器

[root@dbc-server-554 nginx]# ll etc/
total 4
-rw-r--r-- 1 root root 2682 Jan 17 10:28 sysctl
drwxr-xr-x 2 root root    6 Jan 17 10:41 sysctl.conf
[root@dbc-server-554 nginx]# rm etc/sysctl.conf/ -rf
[root@dbc-server-554 nginx]# touch etc/sysctl.conf
[root@dbc-server-554 nginx]# docker run -d -P -v /root/docker/nginx/nginx/etc/sysctl.conf:/etc/sysctl.conf:ro sshdnginx
c83f9ba859e9f092ffb4939a405d0d3c209eb6d2fa839e28680edb1c3fd433df

容器中配置文件和宿主机一致

当然我们可以直接在dockerfile中COPY配置文件,此处只是趣味尝试

9.2.4 相关资料

Nginx官网:https://www.nginx.com
Nginx官方仓库:https://github.com/nginx/nginx
Nginx官方镜像:https://hub.docker.com/_/nginx/
Nginx官方镜像仓库:https://github.com/nginxinc/docker-nginx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值