使用 Docker 构建静态网站服务器示例

 2017年03月03日    1342     声明


介绍完Docker 容器镜像与仓库构建镜像等基础知识后,接下来几篇将介绍一些Docker 使用示例。本篇我们将基于Dockerfile文件构建一个Nginx静态网站服务器,并使用这个服务器运行一个存在于宿主机上的静态网站,并基于Docker容器卷实现对这个网站的实时更新。

  1. Dockerfile及初始化
  2. 构建镜像及网站
  3. 运行容器
  4. 网站修改

在本文中,我们会使用Nginx Web服务器来搭建一个简单的网站服务器,网站命令为petweb

1. Dockerfile及初始化

首先,创建一个目录,并在其中创建Dockerfile文件。

$ mkdir petweb
$ cd petweb
$ touch Dockerfile


1.1 创建Nginx配置文件

我们会使用Nginx做为Web服务器,用于运行网站,要运行网站还需要一些配置文件。在示例目录中创建一个nginx目录,用于保存这些配置文件:

$ mkdir nginx
cd nginx

创建Nginx全局配置nginx.conf及站点配置文件petweb.conf

$ touch nginx.conf
$ vi nginx.conf

nginx.conf文件内容如下:

user www-data;
worker_processes 4;
pid /run/nginx.pid;
daemon off;

events {  }

http {
  sendfile on;
  tcp_nopush on;
  tcp_nodelay on;
  keepalive_timeout 65;
  types_hash_max_size 2048;
  include /etc/nginx/mime.types;
  default_type application/octet-stream;
  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;
  gzip on;
  gzip_disable "msie6";
  include /etc/nginx/conf.d/*.conf;
}

在这个配置方中,我们通过daemon off指定Nginx以非守护进程的模式运行(前台运行),这样就可以使Nginx在容器内保持运行。

注意:Nginx默认是以守护进程的模式运行的,在这种模式下,守护进程被fork启动后,启动守护进程的原始进程就会退出,Docker 容器也会随之停止。因此,需要通过前台运行的方式使容器保持运行。

$ touch petweb.conf
$ vi petweb.conf

petweb.conf文件内容如下:

server {
  listen          0.0.0.0:80;
  server_name     _;

  root            /var/www/html/petweb;
  index           index.html index.htm;

  access_log      /var/log/nginx/default_access.log;
  error_log       /var/log/nginx/default_error.log;
}

在这个文件中,我们指定了Nignx监听80端口,并指定网站在服务器目录/var/www/html/petweb


1.2 初始化Dockerfile

接下来编辑petweb网的Dockerfile

$ cd ..
$ vi Dockerfile

Dockerfile文件内容如下:

FROM ubuntu:16.04
LABEL creater="IT笔录" description="这是一个静态网站" version="1.0"
ENV REFRESHED_AT 2017-02-26
RUN apt-get -yqq update && apt-get install -yqq nginx
RUN mkdir -p /var/www/html/petweb
ADD nginx/petweb.conf /etc/nginx/conf.d/
ADD nginx/nginx.conf /etc/nginx/nginx.conf
EXPOSE 80

在这个Dockerfile文件中,包含了以下内容:

  1. 安装Nginx
  2. 通过LABEL添加了一些镜像描述
  3. 在容器内创建/var/www/html/petweb注意这个目录也是我们petweb.conf文件中所配置的站点根目录
  4. 然后通过ADD命令将本地配置文件添加到了镜像中
  5. 最后公开了容器的80端口


2. 构建镜像及网站

2.1 构建镜像

使用刚创建的Dockerfile文件,通过docker build构建新镜像,并将镜像命名为itbilu/nginx

$ sudo docker build -t itbilu/nginx .

命令执行完成后,会生成一个新镜像。可以通过docker history查看镜像的分层关系及构建过程:

$ sudo docker history itbilu/nginx
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
fcdae3cd7037        About an hour ago   /bin/sh -c #(nop)  EXPOSE 80/tcp                0 B                 
657e30fcad6b        About an hour ago   /bin/sh -c #(nop) ADD file:df60f3554177125...   414 B               
9a4a73d7965e        About an hour ago   /bin/sh -c #(nop) ADD file:0b0356863b20464...   249 B               
6ab912797ab9        About an hour ago   /bin/sh -c mkdir -p /var/www/html/petweb        0 B                 
91776884e69c        About an hour ago   /bin/sh -c apt-get -yqq update && apt-get ...   96.7 MB             
638db5680761        About an hour ago   /bin/sh -c #(nop)  ENV REFRESHED_AT=2017-0...   0 B                 
57aa9a5a8bda        About an hour ago   /bin/sh -c #(nop)  LABEL creater=IT笔录 desc...   0 B                 
f49eec89601e        5 weeks ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0 B                 
<missing>          5 weeks ago         /bin/sh -c mkdir -p /run/systemd && echo '...   7 B                 
<missing>          5 weeks ago         /bin/sh -c sed -i 's/^#\s*\(deb.*universe\...   1.9 kB              
<missing>          5 weeks ago         /bin/sh -c rm -rf /var/lib/apt/lists/*          0 B                 
<missing>          5 weeks ago         /bin/sh -c set -xe   && echo '#!/bin/sh' >...   745 B               
<missing>          5 weeks ago         /bin/sh -c #(nop) ADD file:68f83d996c38a09...   129 MB


2.2 创建petweb网站

镜像构建完成后,就可以通过新创建的镜像运行网站容器,运行前我们先创建静态网站站。

创建网站目录website,并其中创建网站的HTML文件。

$ mkdir website
$ cd website
$ touch index.html
$ vi index.html

网站建设不在本文的介绍范围,在本例中只创建一个网站文件index.html,用于演示基于Docker进行站点管理和更新过程。文件内容如下:

<!DOCTYPE html>
<html>
<head>
  <title>PetWeb</title>
</head>
<body>
<h1>这是一个名叫<em>PetWeb</em>的静态网站</h1>
<p>虽然网站只有一个文件,但能够演示基于Docker进行站点管理和更新过程。</p>
<p>来自:<a href="https://itbilu.com" target="_blank">IT笔录</a></p>
</body>
</html>

编辑完成后,返回上层目录:

$ cd ..


3. 运行容器

接下来,使用新构建的镜像来运行一个容器,运行容器时将刚创建的静态网站挂载到容器中:

$ sudo docker run -d -p 80 --name petweb \
-v $PWD/website:/var/www/html/petweb \
itbilu/nginx nginx

在这个命令中,我们使用itbilu/nginx容器创建并运行了一个容器,容器名为petweb。创建容器时,通过-v参数将宿主机的$PWD/website目录做为卷挂载到了容器的/var/www/html/petweb。而/var/www/html/petweb目录就是在创建镜像,通过petweb.conf配置文件指定的站点在容器内的工作目录。

关于卷:是被一个或多个容器内所使用的目录,卷可以绕过联合文件系统,对卷内数据的修改会即时生效。且创建和修改镜像时,卷是不被包含到镜像中的。因此,卷非常适用于存放频繁改动、而又不必提交到镜像中的数据,或需要在多个容器间共享的数据等。更多关于卷的介绍请参考:

为容器添卷时,还可以通过rwro参数指定容器内目录的读写状态。如,设置为只读状态:

$ sudo docker run -d -p 80 --name petweb \
-v $PWD/website:/var/www/html/petweb:ro \
itbilu/nginx nginx


运行容器后,可以通过docker ps命令看到运行中的容器:

$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                   NAMES
73a4dcd7ba7b        itbilu/nginx        "nginx"             3 hours ago         Up 3 hours          0.0.0.0:32771->80/tcp   petweb

如上所示,由于运行容器时我们没指定本机端口,因此随机分配了一个32771端口映射到了容器的80端口。这时,可以浏览器输入localhost:32771127.0.0.1:32771来查看网站的运行状态:

Docker运行静态网站


4. 网站修改

经过上面的步骤我们已经成功运行了一个静态网站。由于业务发展,我们需要修改这个静态站,这时该怎么办呢?

在前面运行容器时,我们通过-v参数,以卷的方式将本地目录挂载到了容器内。要修改站点时,只需要在本地目录修改即可。

如,在本目录将index.html修改为如下内容:

<!DOCTYPE html>
<html>
<head>
  <title>PetWeb</title>
</head>
<body>
<h1>这是一个用Docker运行的,名叫<em>PetWeb</em>的静态网站</h1>
<p>虽然网站只有一个文件,但能够演示基于Docker进行站点管理和更新过程。</p>
<p>来自:<a href="https://itbilu.com" target="_blank">IT笔录</a></p>
</body>
</html>

现在刷新浏览器,看到效果如下:

卷数据修改

可以看到,修改已经成功了。利用卷的这一特征,我们可以非常简单的修改容器外部或容器间共享的数据。

在实际生产环境中也是如此,在生产环境中,我们可为服务器(如:Nginx、Apache)配置一个容器、给不同的开发框架配置一个容器(如:Node.js、PHP)、给数据库配置一个容器,等等。再通过卷在容器间或容器与宿主机之间实现数据的共享,从而实现应用的模块化布暑。