Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

自前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画像キャッシュサーバができました。パフォーマンスも、非常に軽快でいい感じです。

zaru
basicinc
マーケティングとテクノロジーで社会のあらゆる問題を解決する集団
https://tech.basicinc.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした