LoginSignup
58
51

More than 5 years have passed since last update.

nginxの画像キャッシュサーバにリサイズ機能を付けた

Posted at

自前CDNじゃないけど、画像をキャッシュしてくれるプロキシサーバをnginxでたててみて、さらに画像のリサイズ機能も欲しいなーと思ったのでやってみました。Akamaiさんのリサイズ機能は貧乏人にはちょっとお高いので…。

以下、構成図です。nginxのみで運用可能です。オリジンサーバは、なんでもいいです。

スクリーンショット 2015-07-29 13.01.20.png

これで幅100px / 縦100px / JPG品質100にリサイズされるようにします。

前提

  • nginx v1.8.0

nginxのインストール

画像リサイズのモジュール(http_image_filter_module)を有効にしたいので、パッケージじゃなくて、ソースからビルドします。

$ sudo yum install -y gd gd-devel gcc pcre pcre-devel openssl openssl-devel
$ cd /tmp
$ wget http://nginx.org/download/nginx-1.8.0.tar.gz
$ tar zxvf nginx-1.8.0.tar.gz
$ cd nginx-1.8.0
$ ./configure --with-http_image_filter_module
$ make
$ sudo make install
$ /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.8.0
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC)
configure arguments: --with-http_image_filter_module
$ sudo useradd --shell /sbin/nologin nginx

nginxの起動スクリプト

ソースからビルドすると、起動するの面倒なのでスクリプト書きます。

$ sudo vi /etc/rc.d/init.d/nginx
/etc/rc.d/init.d/nginx
#!/bin/sh
#
# nginx - this script starts and stops the nginx daemon
#
# chkconfig:   - 85 15
# description:  Nginx is an HTTP(S) server, HTTP(S) reverse \
#               proxy and IMAP/POP3 proxy server
# processname: nginx
# config:      /etc/nginx/nginx.conf
# config:      /etc/sysconfig/nginx
# pidfile:     /var/run/nginx.pid

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

nginx="/usr/local/nginx/sbin/nginx"
prog=$(basename $nginx)

NGINX_CONF_FILE="/usr/local/nginx/conf/nginx.conf"

[ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx

lockfile=/var/lock/subsys/nginx

make_dirs() {
   # make required directories
   user=`$nginx -V 2>&1 | grep "configure arguments:" | sed 's/[^*]*--user=\([^ ]*\).*/\1/g' -`
   if [ -z "`grep $user /etc/passwd`" ]; then
       useradd -M -s /bin/nologin $user
   fi
   options=`$nginx -V 2>&1 | grep 'configure arguments:'`
   for opt in $options; do
       if [ `echo $opt | grep '.*-temp-path'` ]; then
           value=`echo $opt | cut -d "=" -f 2`
           if [ ! -d "$value" ]; then
               # echo "creating" $value
               mkdir -p $value && chown -R $user $value
           fi
       fi
   done
}

start() {
    [ -x $nginx ] || exit 5
    [ -f $NGINX_CONF_FILE ] || exit 6
    make_dirs
    echo -n $"Starting $prog: "
    daemon $nginx -c $NGINX_CONF_FILE
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    killproc $prog -QUIT
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    configtest || return $?
    stop
    sleep 1
    start
}

reload() {
    configtest || return $?
    echo -n $"Reloading $prog: "
    killproc $nginx -HUP
    RETVAL=$?
    echo
}

force_reload() {
    restart
}

configtest() {
  $nginx -t -c $NGINX_CONF_FILE
}

rh_status() {
    status $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}

case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart|configtest)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
            ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
        exit 2
esac
$ sudo chmod 755 /etc/rc.d/init.d/nginx
$ sudo chkconfig nginx on
$ sudo service nginx start

これで、パッケージとおなじ感覚で使うことができます。

nginxの設定

Proxyキャッシュの設定 + 特定の条件下の時、リサイズ&切り抜きをするように設定します。

/usr/local/nginx/conf/nginx.conf
user  nginx;
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    # キャッシュするディレクトリ/階層レベル/サイズ/有効期限を設定可能
    proxy_cache_path /var/cache/nginx/cache levels=1:2 keys_zone=cachezone:64m max_size=20000m inactive=1d;
    server {
        listen 80;
        server_name _;
        root /var/www/html;

        location / {
            # JPG画像のみキャッシュするように設定
            set $do_not_cache 0;
            if ($request_method != GET) {
                set $do_not_cache 1;
            }
            if ($uri !~* ".jpg") {
                set $do_not_cache 1;
            }
            proxy_cache_bypass $do_not_cache;

            proxy_pass http://localhost:8080;
            proxy_cache cachezone;
            proxy_cache_key $scheme$host$uri$arg_w$arg_h$arg_type$arg_q;
            proxy_cache_valid  200 302 1d;
            proxy_cache_valid 404 5m;
            proxy_cache_valid any 1m;

            expires 1d;
        }
    }

    server {
        listen 8080;
        server_name _;
        root /var/www/html;
        resolver 8.8.8.8;

        location ~ /(.*\.jpg)$ {

            # キャッシュ対象ホスト名
            set $imghost www.example.com;
            set $file $1;
            set $width 150;
            set $height 150;
            set $quality 75;

            if ($query_string !~ .*=.*) {
              rewrite ^ /original last;
            }

            if ($arg_w ~ (\d*)) {
                set $width $1;
            }
            if ($arg_h ~ (\d*)) {
                set $height $1;
            }
            if ($arg_q ~ (100|[1-9][0-9]|[1-9])) {
                set $quality $1;
            }

            if ($arg_type = "resize") {
                rewrite ^ /resize last;
            }

            rewrite ^ /crop last;
        }

        location /original {
            internal;
            proxy_pass http://$imghost/$file;
        }

        location /resize {
            internal;
            proxy_pass http://$imghost/$file;
            image_filter  resize  $width  $height;
            image_filter_jpeg_quality  $quality;
            error_page 415 = @empty;
        }

        location /crop {
            internal;
            proxy_pass http://$imghost/$file;
            image_filter  crop  $width  $height;
            image_filter_jpeg_quality  $quality;
            error_page 415 = @empty;
        }

        location @empty {
            empty_gif;
        }
    }
}

以上で、画像のキャッシュもしつつ、リサイズも行えるnginx画像キャッシュサーバができました。パフォーマンスも、非常に軽快でいい感じです。

58
51
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
58
51