---
title: 3.4、Docker(4)-nginx
date: 2018-6-27 11:35:27
tags: 
  - docker
  - nginx
categories: 
  - linux
---

1. 使用docker部署nginx
2. 添加ssl支持
3. 添加http/2服务器推送支持
<!-- more -->

### 拉取nginx镜像
不填写版本号默认拉取最新版本的, 也就是latest
```bash
docker pull nginx
```
![nginx image](/images/linux/nginx_image.jpg)

### 启动容器
现在首先创建一个目录作为页面的根目录, 比如创建名为 **html**的目录
在里面创建一个测试页面index.html
```bash
docker run \
-d \
--rm \
--name testnginx \
--volume "/test/html":/usr/share/nginx/html \
-p 8080:80 \
nginx:latest
```
+ volume是本地目录与容器内目录的映射, 前面是本地目录, 后面是容器内目录
也可以使用`mount`参数
写作 `--mount type=bind,source=/test/html,target=/usr/share/nginx/html`
(如果加上readonly, 则在容器内无法对该目录进行写入操作)
+ 目录映射的信息可以通过`docker inspect [ContainerId]`来查看
```json
"Mounts": [{
  "Type": "bind",
  "Source": "/test/html",
  "Destination": "/usr/share/nginx/html",
  "Mode": "",
  "RW": true,
  "Propagation": "rprivate"
}],

```
+ name 可以省略

现在我们可以访问 http://localhost:8080/ 来测试服务是否启动正常的
如果一切正常, 应该可以看到刚才编写的index.html页面内容

### 添加ssl支持
#### 生成证书
需要是在生产环境运行, 需要向证书颁发机构申请正式的证书
这里为了测试, 直接使用openssl生成

前提是需要安装openssl
之后执行
```bash
openssl req \
  -x509 \
  -nodes \
  -days 365 \
  -newkey rsa:2048 \
  -keyout example.key \
  -out example.crt
```
把生成的证书文件放到conf/certs里面

#### 修改nginx配置
如果要添加ssl支持, 可以使用https协议访问, 我们就需要修改配置文件
所以还需要把配置文件的目录映射出来
```bash
# 先把配置文件的目录整个拷贝到本地
docker container cp [ContainerId]:/etc/nginx ./
mv nginx conf #重命名
```
这里表示把指定容器中的指定目录, 拷贝到当前目录下
然后修改其中的配置文件
![nginx配置文件](/images/linux/nginx配置文件.jpg)
观察发现其中引入了conf.d里面的所有conf文件
所以我们可以直接去修改conf.d里面的
这样配置文件分离, 比较便于维护

修改`conf.d/default.conf`在最后添加
```
server {
  listen 443 ssl http2;
  server_name  localhost;

  ssl                      on;
  ssl_certificate          /etc/nginx/certs/example.crt;
  ssl_certificate_key      /etc/nginx/certs/example.key;

  ssl_session_timeout  5m;

  ssl_ciphers HIGH:!aNULL:!MD5;
  ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
  ssl_prefer_server_ciphers   on;

  location / {
      root   /usr/share/nginx/html;
      index  index.html index.htm;
  }
}
```
#### 启动容器
先把之前启动的容器停止
`docker container [ContainerId] stop`
这次启动需要把配置文件的目录也添加上映射
```bash
docker run \
-d \
--rm \
--name testnginx \
--volume "/test/html":/usr/share/nginx/html \
--volume "/test/conf":/etc/nginx \
-p 8080:80 \
-p 8443:443 \
nginx:latest
```
> 这里容器内程序启动占用的端口取决于配置, 如果有修改, 端口映射需要对应

然后就可以尝试访问 https://localhost:8443/ 了
当然自己生成的证书浏览器是不信任的, 添加例外即可

### HTTP/2新特性
1. 二进制分帧 : HTTP/2 采用二进制格式传输数据，而非 HTTP 1.x 的文本格式，二进制协议解析起来更高效
2. 多路复用 : 所有的请求都是通过一个TCP连接并发完成, HTTP 1.x中，如果想并发多个请求，必须使用多个TCP链接
3. 服务器推送 : 服务端可以在发送页面HTML时主动推送其它资源，而不用等到浏览器解析到相应位置，发起请求再响应
4. 头部压缩 : 对消息头采用HPACK（专为http/2头部设计的压缩格式）进行压缩传输，能够节省消息头占用的网络的流量
