前言
从七牛上线的时候就开始使用七牛云存储的服务,对于其中的图片处理一直比较好奇,只需要简单的在图片的访问链接上加上参数,就可以按照定义的功能,得到裁剪或者处理好的图片。
对于实现的机制,也不能说是完全没有概念,只是从来没有认真的思考或者尝试着动手实现一下。所以一直只是一个当作缩放工具来用的普通用户;最近正好看到一个使用 nginx
和 libgb
实现的图片处理服务,感觉非常简单就可以搭建,果断尝试了之后,确实 get 了一项很实用的技能或者说是工具。
运行原理和机制
实现一个图片处理服务器本身如果不去自己实现 web 服务器和图片处理的核心程序的话,只是以使用功能为目的的话,图片处理功能更多在于技术选型和运维。定义好资源访问的路由规则和调用图片处理的语法之后,简单的运行原理应该包含以下步骤:
- web 服务器将资源请求转发给有处理能力并且已经注册的应用服务器或者调用本地程序;
- 应用服务器(例如 PHP)根据路由规则,和应用程序本身的设计,定位到路由对应的图片二进制文件;
- 根据路由,或者其他 http header 信息,解析要对图片进行的解析操作;
- 应用服务器自己实现,或者调用其他的图片处理库,或者调用其他程序(例如 ImageMagick),对二进制文件进行处理,获得处理好的图片;
- 将图片按照 http 协议,返回请求的客户端。
自己设计实现对 ImageMagick、GD
的封装,或者是尝试自己编写处理图片的程序,都是很有趣的事情,应该找机会亲自动手实践。
解决方案
最近偶然看到的一个方案是,使用 nginx 提供的 nginx-module-image-filter
,nginx
的扩展模块,就可以提供最基础的图片裁剪服务器,简单了解之后,马上着手使用 docker
开始搭建 nginx
图片处理服务器。
我们计划使用 Docker 进行运行环境搭建。先手动组建创建服务。
1.启动一个干净的 centos 环境
首先启动一个 centos
容器,并且将图片资源挂载上去。
bash
docker run -it -p 8888:80 -v /data/images:/data/images --name images centos /bin/bash
其中/data/images
是本地的资源,并且将8888
端口和内部服务端口映射
2.执行必要的库安装操作
ruby
//安装执行过程依赖库
yum install -y gd-devel wget
yum -y install gcc gcc-c++ kernel-devel make
//下载最新的nginx包
wget http://nginx.org/download/nginx-1.16.1.tar.gz
tar -xzvf nginx-1.16.1.tar.gz
//下载依赖正则库
wget https://jaist.dl.sourceforge.net/project/pcre/pcre/8.43/pcre-8.43.tar.gz
tar -xzvf pcre-8.43.tar.gz
//进入目录进行编译工作
cd nginx-1.16.1
./configure --prefix=/usr/local/nginx --with-http_image_filter_module --with-pcre=../pcre-8.43
make
make install
3.启动
在./configure
配置完后,会写出 nginx
相关的配置信息,注意保存。启动和配置都需要。部分核心配置如下:
lua
nginx binary file: "/usr/local/nginx/sbin/nginx"
nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
nginx pid file: "/usr/local/nginx/logs/nginx.pid"
nginx error log file: "/usr/local/nginx/logs/error.log"
nginx http access log file: "/usr/local/nginx/logs/access.log"
二进制的程序路径为 sbin/nginx
配置文件地址 nginx.conf
现在启动 nginx,通过 ip 访问 nginx 出现 nginx 的首页。(http://192.168.41.56:8888/
)
修改配置文件如下:
ini
location /images {
root /data/images;
index index.html;
image_filter resize 210 210;
image_filter rotate 90;
#error_page 415 = /empty;
}
其中 image_filter
rotate
的取值只能是 90
180
和 270
. 自然也可以使用 proxy_pass
方法进行映射。映射到其他的服务
ini
location /img/ {
proxy_pass http://backend;
image_filter resize 150 100;
image_filter rotate 90;
error_page 415 = /empty;
}
location = /empty {
empty_gif;
}
通过设置 proxy_pass
,我们要对某个网站上的图片进行裁剪,只需要将代理设置到指向该网站就可以了。
image_filter resize 150 100
; 就是重新调整图片的尺寸。
image_filter off
; 配置可以关闭 image filter
。
通过结合 nginx 的解析规则,我们就可以根据 url
链接的参数,动态的制定要缩放图片的大小。
bash
location ~* (.*\.(jpg|gif|png))!/w/(.*)/h/(.*)$ {
set $width $3;
set $height $4;
rewrite "(.*\.(jpg|gif|png))(.*)$" $1;
}
location ~* /images/.*\.(jpg|gif|png)$ {
root /data/images;
image_filter resize $width $height;
}
通过访问地址 http://192.168.41.56:8888/images/1.jpg!/w/210/h/210
就可以访问到按照比例出现的图。注意这里面有个问题是:图像显示是按照比例呈现的。并非任意的比都可以实现。 并且也不会超过其最大的比例
在纯净的 centos 中实现后,可以使用 Dockerfile 进行编写。
4.Dockerfile 编写
Docker 的编写见下面 文件 docker-nginx-img
bash
FROM index.tenxcloud.com/tenxcloud/docker-centos
#FROM centos
MAINTAINER Stone, codingstone@163.com
RUN yum install -y gd-devel wget \
&& yum -y install gcc gcc-c++ kernel-devel make \
&& mkdir /home/liuwill \
&& cd /home/liuwill \
&& wget wget http://nginx.org/download/nginx-1.16.1.tar.gz \
&& tar -xzvf nginx-1.16.1.tar.gz \
&& wget https://jaist.dl.sourceforge.net/project/pcre/pcre/8.43/pcre-8.43.tar.gz \
&& tar -xzvf pcre-8.43.tar.gz \
&& cd nginx-1.16.1 \
&& ./configure --prefix=/usr/local/nginx --with-http_image_filter_module --with-pcre=../pcre-8.43 \
&& make \
&& make install
#RUN echo -e 'PATH=$PATH:/usr/local/nginx/sbin\nexport PATH' >> /etc/profile
#RUN source /etc/profile
ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/nginx/sbin
WORKDIR /var/www
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]