Repository: wantedly/nginx-image-server Branch: master Commit: 72b059f7bd47 Files: 22 Total size: 27.8 KB Directory structure: gitextract_dwuep06d/ ├── .dockerignore ├── .gitignore ├── .travis.yml ├── Dockerfile ├── LICENSE ├── README.md ├── coreos/ │ ├── Vagrantfile │ ├── config.rb │ └── user-data.yml.erb ├── files/ │ ├── mime.types │ ├── nginx.conf │ └── validator.pm ├── script/ │ ├── bootstrap │ ├── build │ ├── run │ ├── run-infrataster │ ├── run-locust │ └── test ├── test/ │ ├── feature/ │ │ └── spec/ │ │ ├── nginx_image_server_spec.rb │ │ └── spec_helper.rb │ └── performance/ │ └── locustfile.py └── wercker.yml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .dockerignore ================================================ * !Dockerfile !files/* ================================================ FILE: .gitignore ================================================ .env .DS_Store locustfile.pyc user-data .vagrant ================================================ FILE: .travis.yml ================================================ sudo: required services: - docker script: - docker -v - docker build -t quay.io/wantedly/nginx-image-server . - script/run -d - script/run-infrataster notifications: slack: secure: C5l4fgeuirkGPI4BYZP1onHY1FbYbth5UuGRZzmJ/6OBMdwV4HdHl7Gbt92NiD+7EhtWOh1qtqgFPakoVZjrrva3vS/cR1drvh80qQbF/OjZRsR68p0kjJDEn5uJf66iP0DBkFRWYliE0CILXha6T/5xxOQthuoI7OWfrI8SQi0= ================================================ FILE: Dockerfile ================================================ FROM ubuntu:14.04 ENV NGINX_VERSION 1.10.0 ENV NGX_SMALL_LIGHT_VERSION 0.9.1 ENV IMAGEMAGICK_VERSION 6.8.6-8 # Install dependency packages RUN apt-get update && \ apt-get install -y \ binutils-doc \ bison \ flex \ g++ \ gettext \ libpcre3 \ libpcre3-dev \ libssl-dev \ libperl-dev \ make && \ rm -rf /var/lib/apt/lists/* # Build ImageMagick with WebP support RUN mkdir -p /tmp/imagemagick && \ cd /tmp/imagemagick && \ echo "\ndeb-src http://archive.ubuntu.com/ubuntu/ trusty main restricted" >> /etc/apt/sources.list && \ apt-get update && \ apt-get build-dep -y imagemagick && \ apt-get install -y libwebp-dev devscripts checkinstall && \ curl -L https://launchpad.net/imagemagick/main/${IMAGEMAGICK_VERSION}/+download/ImageMagick-${IMAGEMAGICK_VERSION}.tar.gz > \ ImageMagick-${IMAGEMAGICK_VERSION}.tar.gz && \ tar zxf ImageMagick-${IMAGEMAGICK_VERSION}.tar.gz && \ cd ImageMagick-${IMAGEMAGICK_VERSION} && \ ./configure \ --prefix=/usr \ --sysconfdir=/etc \ --libdir=/usr/lib/x86_64-linux-gnu \ --enable-shared \ --with-modules \ --disable-openmp \ --with-webp=yes \ LDFLAGS=-L/usr/local/lib \ CPPFLAGS=-I/usr/local/include && \ make && \ checkinstall -y && \ rm -rf /tmp/imagemagick && \ rm -rf /var/lib/apt/lists/* # Fetch and unarchive nginx source RUN curl -L http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz > /tmp/nginx-${NGINX_VERSION}.tar.gz && \ cd /tmp && \ tar zxf nginx-${NGINX_VERSION}.tar.gz # Fetch and unarchive ngx_small_light module RUN curl -L https://github.com/cubicdaiya/ngx_small_light/archive/v${NGX_SMALL_LIGHT_VERSION}.tar.gz > /tmp/ngx_small_light-${NGX_SMALL_LIGHT_VERSION}.tar.gz && \ cd /tmp && \ tar zxf ngx_small_light-${NGX_SMALL_LIGHT_VERSION}.tar.gz && \ cd /tmp/ngx_small_light-${NGX_SMALL_LIGHT_VERSION} && \ ./setup # Compile nginx RUN cd /tmp/nginx-${NGINX_VERSION} && \ ./configure \ --prefix=/opt/nginx \ --conf-path=/etc/nginx/nginx.conf \ --sbin-path=/opt/nginx/sbin/nginx \ --with-http_stub_status_module \ --with-http_perl_module \ --with-pcre \ --add-module=/tmp/ngx_small_light-${NGX_SMALL_LIGHT_VERSION} && \ make && \ make install && \ rm -rf /tmp/* RUN mkdir -p /etc/nginx && \ mkdir -p /opt/nginx/perl/lib && \ mkdir -p /var/run && \ mkdir -p /etc/nginx/conf.d && \ mkdir -p /var/www/nginx/cache && \ mkdir -p /var/www/nginx/images && \ mkdir -p /var/www/nginx/tmp # Add config files COPY files/nginx.conf /etc/nginx/nginx.conf COPY files/mime.types /etc/nginx/mime.types COPY files/validator.pm /opt/nginx/perl/lib/validator.pm EXPOSE 80 8090 CMD ["/opt/nginx/sbin/nginx"] ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2014-2016 Wantedly, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # Nginx Image Server [![Docker Repository on Quay.io](https://quay.io/repository/wantedly/nginx-image-server/status "Docker Repository on Quay.io")](https://quay.io/repository/wantedly/nginx-image-server) [![Build Status](https://travis-ci.org/wantedly/nginx-image-server.svg)](https://travis-ci.org/wantedly/nginx-image-server) Docker Image for [Nginx](http://nginx.org/) server for image processing with [ngx_small_light](https://github.com/cubicdaiya/ngx_small_light). It supports resizing/cropping/formatting (`png`, `webp`...etc) of images stored in local storages or AWS S3. Please see https://github.com/cubicdaiya/ngx_small_light for more information about image processing. ## SUPPORTED TAGS * `latest` * Nginx 1.10.0 * ngx_small_light 0.9.1 * ImageMagick 6.8.6-8 (Q16) with WebP support ## HOW TO USE ```bash # Get the docker image $ docker pull quay.io/wantedly/nginx-image-server # Fetch an example image to try image-processing local image $ curl -L https://raw.githubusercontent.com/wantedly/nginx-image-server/master/examples/example.jpg > \ /tmp/example.jpg # Start the image server $ docker run \ --rm \ -it \ --name nginx-image-server \ -p 80:80 \ -p 8090:8090 \ -v /tmp/example.jpg:/var/www/nginx/images/example.jpg \ -e "SERVER_NAME=image.example.com" \ -e "S3_HOST=.s3.amazonaws.com" \ quay.io/wantedly/nginx-image-server:latest ``` Then you can try image-processing by accessing * **Images in S3**: `http:///small_light(dh=400,da=l,ds=s)/` * **Images in Local**: `http:///local/small_light(dh=400,da=l,ds=s)/images/example.jpg` And `http://:8090/status` retruns the nginx status. ### Custom configuration You can build a docker image includes your own `nginx.conf`: ``` FROM quay.io/wantedly/nginx-image-server COPY nginx.conf /etc/nginx/nginx.conf ``` Then build with `docker build -t your-nginx-image-server .` and run: ```bash $ docker run \ -d \ --name your-nginx-image-server \ -p 80:80 \ your-nginx-image-server ``` Be sure to include `daemon off;` in your custom configuration to run Nginx in the foreground. Otherwise your container will stop immediately after starting. ## HOW TO DEVELOP ```bash # on your local machine $ git clone https://github.com/wantedly/nginx-image-server.git && cd nginx-image-server $ script/bootstrap $ cp .env.sample .env ``` ``` # .env TIMEZONE=Asia/Tokyo ``` ``` $ vagrant up $ vi Dockerfile # login to VM and test it $ vagrant ssh @core-01 $ cd share @core-01 $ docker build -t=quay.io/wantedly/nginx-image-server . @core-01 $ script/test ``` ## TEST [![wercker status](https://app.wercker.com/status/e1d50221515bacea622f6a6f5f0adde6/s/master "wercker status")](https://app.wercker.com/project/bykey/e1d50221515bacea622f6a6f5f0adde6) ### Feature(behavior) test Behavior test with [infrataster](https://github.com/ryotarai/infrataster). Test files are under `test/feature` directory. You can run this test with follwing script: ```bash $ script/test ``` ### Performance test Performance test with [locust](http://locust.io/). Test files are under `test/performance` directory. You can run locust with follwing script: ```bash # Run target container $ script/run # Export target IP $ export TARGET_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' nginx-image-server) # Run locust as WebTool $ script/run-locust -f locustfile.py -H http://${TARGET_IP} # Run locust as CLI $ script/run-locust -f locustfile.py -H http://${TARGET_IP} --no-web -c 5 -r 1 -n 10 ``` ## LICENSE [![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE) ================================================ FILE: coreos/Vagrantfile ================================================ # -*- mode: ruby -*- # # vi: set ft=ruby : require 'fileutils' Vagrant.require_version ">= 1.6.0" CLOUD_CONFIG_PATH = File.join(File.dirname(__FILE__), "user-data") CONFIG = File.join(File.dirname(__FILE__), "config.rb") # Defaults for config options defined in CONFIG $num_instances = 1 $update_channel = "alpha" $enable_serial_logging = false $vb_gui = false $vb_memory = 1024 $vb_cpus = 1 # Attempt to apply the deprecated environment variable NUM_INSTANCES to # $num_instances while allowing config.rb to override it if ENV["NUM_INSTANCES"].to_i > 0 && ENV["NUM_INSTANCES"] $num_instances = ENV["NUM_INSTANCES"].to_i end if File.exist?(CONFIG) require CONFIG end Vagrant.configure("2") do |config| # always use Vagrants insecure key config.ssh.insert_key = false config.vm.box = "coreos-%s" % $update_channel config.vm.box_version = ">= 308.0.1" config.vm.box_url = "http://%s.release.core-os.net/amd64-usr/current/coreos_production_vagrant.json" % $update_channel config.vm.provider :vmware_fusion do |vb, override| override.vm.box_url = "http://%s.release.core-os.net/amd64-usr/current/coreos_production_vagrant_vmware_fusion.json" % $update_channel end config.vm.provider :virtualbox do |v| # On VirtualBox, we don't have guest additions or a functional vboxsf # in CoreOS, so tell Vagrant that so it can be smarter. v.check_guest_additions = false v.functional_vboxsf = false end # plugin conflict if Vagrant.has_plugin?("vagrant-vbguest") then config.vbguest.auto_update = false end (1..$num_instances).each do |i| config.vm.define vm_name = "core-%02d" % i do |config| config.vm.hostname = vm_name if $enable_serial_logging logdir = File.join(File.dirname(__FILE__), "log") FileUtils.mkdir_p(logdir) serialFile = File.join(logdir, "%s-serial.txt" % vm_name) FileUtils.touch(serialFile) config.vm.provider :vmware_fusion do |v, override| v.vmx["serial0.present"] = "TRUE" v.vmx["serial0.fileType"] = "file" v.vmx["serial0.fileName"] = serialFile v.vmx["serial0.tryNoRxLoss"] = "FALSE" end config.vm.provider :virtualbox do |vb, override| vb.customize ["modifyvm", :id, "--uart1", "0x3F8", "4"] vb.customize ["modifyvm", :id, "--uartmode1", serialFile] end end if $expose_docker_tcp config.vm.network "forwarded_port", guest: 2375, host: ($expose_docker_tcp + i - 1), auto_correct: true end config.vm.provider :vmware_fusion do |vb| vb.gui = $vb_gui end config.vm.provider :virtualbox do |vb| vb.gui = $vb_gui vb.memory = $vb_memory vb.cpus = $vb_cpus end ip = "172.17.8.#{i+100}" config.vm.network :private_network, ip: ip # Uncomment below to enable NFS for sharing the host machine into the coreos-vagrant VM. config.vm.synced_folder "../", "/home/core/share", id: "core", :nfs => true, :mount_options => ['nolock,vers=3,udp'] if File.exist?(CLOUD_CONFIG_PATH) config.vm.provision :file, :source => "#{CLOUD_CONFIG_PATH}", :destination => "/tmp/vagrantfile-user-data" config.vm.provision :shell, :inline => "mv /tmp/vagrantfile-user-data /var/lib/coreos-vagrant/", :privileged => true end end end end ================================================ FILE: coreos/config.rb ================================================ require 'erb' require 'dotenv' # Create user-data from erb template Dotenv.load erb = File.open(File.join(File.dirname(__FILE__), "user-data.yml.erb")) { |f| ERB.new(f.read) } File.write(File.join(File.dirname(__FILE__), "user-data"), erb.result(binding)) # To automatically replace the discovery token on 'vagrant up', uncomment # the lines below: # #if File.exists?('user-data') && ARGV[0].eql?('up') # require 'open-uri' # require 'yaml' # # token = open('https://discovery.etcd.io/new').read # # data = YAML.load(IO.readlines('user-data')[1..-1].join) # data['coreos']['etcd']['discovery'] = token # # yaml = YAML.dump(data) # File.open('user-data', 'w') { |file| file.write("#cloud-config\n\n#{yaml}") } #end # # # coreos-vagrant is configured through a series of configuration # options (global ruby variables) which are detailed below. To modify # these options, first copy this file to "config.rb". Then simply # uncomment the necessary lines, leaving the $, and replace everything # after the equals sign.. # Size of the CoreOS cluster created by Vagrant $num_instances=1 # Official CoreOS channel from which updates should be downloaded $update_channel="beta" # Log the serial consoles of CoreOS VMs to log/ # Enable by setting value to true, disable with false # WARNING: Serial logging is known to result in extremely high CPU usage with # VirtualBox, so should only be used in debugging situations #$enable_serial_logging=false # Enable port forwarding of Docker TCP socket # Set to the TCP port you want exposed on the *host* machine, default is 2375 # If 2375 is used, Vagrant will auto-increment (e.g. in the case of $num_instances > 1) # You can then use the docker tool locally by setting the following env var: # export DOCKER_HOST='tcp://127.0.0.1:2375' #$expose_docker_tcp=2375 # Setting for VirtualBox VMs #$vb_gui = false #$vb_memory = 1024 #$vb_cpus = 1 ================================================ FILE: coreos/user-data.yml.erb ================================================ #cloud-config coreos: update: group: beta reboot-strategy: off units: - name: settimezone.service command: start content: | [Unit] Description=Set the timezone [Service] ExecStart=/usr/bin/timedatectl set-timezone <%= ENV["TIMEZONE"] %> RemainAfterExit=yes Type=oneshot - name: docker-tcp.socket command: start enable: true content: | [Unit] Description=Docker Socket for the API [Socket] ListenStream=2375 Service=docker.service BindIPv6Only=both [Install] WantedBy=sockets.target write_files: - path: /etc/ssh/sshd_config permissions: 0600 owner: root:root content: | # Use most defaults for sshd configuration. UsePrivilegeSeparation sandbox Subsystem sftp internal-sftp PermitRootLogin no PasswordAuthentication no ChallengeResponseAuthentication no - path: /etc/ntp.conf content: | # Common pool server 0.pool.ntp.org server 1.pool.ntp.org server 2.pool.ntp.org server 3.pool.ntp.org # - Allow only time queries, at a limited rate. # - Allow all local queries (IPv4, IPv6) restrict default nomodify nopeer noquery limited kod restrict 127.0.0.1 restrict [::1] ================================================ FILE: files/mime.types ================================================ types { text/html html htm shtml; text/css css; text/xml xml; image/gif gif; image/jpeg jpeg jpg; application/javascript js; application/json json; application/atom+xml atom; application/rss+xml rss; text/mathml mml; text/plain txt; text/vnd.sun.j2me.app-descriptor jad; text/vnd.wap.wml wml; text/x-component htc; image/png png; image/tiff tif tiff; image/vnd.wap.wbmp wbmp; image/x-icon ico; image/x-jng jng; image/x-ms-bmp bmp; image/svg+xml svg svgz; image/webp webp; application/java-archive jar war ear; application/mac-binhex40 hqx; application/msword doc; application/pdf pdf; application/postscript ps eps ai; application/rtf rtf; application/vnd.ms-excel xls; application/vnd.ms-powerpoint ppt; application/vnd.wap.wmlc wmlc; application/vnd.google-earth.kml+xml kml; application/vnd.google-earth.kmz kmz; application/x-7z-compressed 7z; application/x-cocoa cco; application/x-java-archive-diff jardiff; application/x-java-jnlp-file jnlp; application/x-makeself run; application/x-perl pl pm; application/x-pilot prc pdb; application/x-rar-compressed rar; application/x-redhat-package-manager rpm; application/x-sea sea; application/x-shockwave-flash swf; application/x-stuffit sit; application/x-tcl tcl tk; application/x-x509-ca-cert der pem crt; application/x-xpinstall xpi; application/xhtml+xml xhtml; application/zip zip; application/octet-stream bin exe dll; application/octet-stream deb; application/octet-stream dmg; application/octet-stream eot; application/octet-stream iso img; application/octet-stream msi msp msm; audio/midi mid midi kar; audio/mpeg mp3; audio/ogg ogg; audio/x-m4a m4a; audio/x-realaudio ra; video/3gpp 3gpp 3gp; video/mp4 mp4; video/mpeg mpeg mpg; video/quicktime mov; video/webm webm; video/x-flv flv; video/x-m4v m4v; video/x-mng mng; video/x-ms-asf asx asf; video/x-ms-wmv wmv; video/x-msvideo avi; } ================================================ FILE: files/nginx.conf ================================================ env SERVER_NAME; env S3_HOST; user root; worker_processes 4; daemon off; #worker_rlimit_nofile error_log /dev/stdout info; pid /var/run/nginx.pid; events { worker_connections 1024; #multi_accept on; #use } http { perl_modules perl/lib; perl_require validator.pm; perl_set $server_name_from_env 'sub { return $ENV{"SERVER_NAME"}; }'; perl_set $s3_host_from_env 'sub { return $ENV{"S3_HOST"}; }'; include /etc/nginx/mime.types; default_type application/octet-stream; #access_log off; access_log /dev/stdout; server_tokens off; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; gzip on; gzip_http_version 1.0; gzip_comp_level 2; gzip_proxied any; gzip_vary off; #gzip_buffers gzip_types text/plain text/css application/x-javascript text/xml application/xml application/rss+xml application/atom+xml text/javascript application/javascript application/json text/mathml; gzip_min_length 1000; gzip_disable MSIE [1-6]\.; server_names_hash_bucket_size 64; types_hash_max_size 2048; types_hash_bucket_size 64; #proxy_read_timeout #client_body_buffer_size #client_max_body_size limit_req_zone $binary_remote_addr zone=default:10m rate=1r/s; proxy_cache_path /var/www/nginx/cache levels=1:2 keys_zone=cache-space:4m max_size=50m inactive=120m; proxy_temp_path /var/www/nginx/tmp; server { listen 80; server_name $server_name_from_env; location ~ ^/(.+)$ { proxy_pass http://localhost:8080; proxy_cache cache-space; proxy_cache_valid 200 60m; } } server { listen 8080; server_name $server_name_from_env; resolver 8.8.8.8; small_light on; location @empty { empty_gif; } location /favicon.ico { empty_gif; access_log off; log_not_found off; } # Image processing for images in local file location ~ ^/local/small_light[^/]*/(.+)$ { set $small_light_maximum_size 3072; perl validator::handler; } # Image processing for images in AWS S3 location ~ ^/small_light[^/]*/(.+)$ { set $small_light_maximum_size 3072; perl validator::handler; } location ~ ^/images/(.+)$ { root /var/www/nginx; error_page 415 = @empty; } location ~ ^/(.+)$ { proxy_pass http://$s3_host_from_env/$1; error_page 415 = @empty; } } server { listen 8090; server_name $server_name_from_env; location /status { stub_status on; access_log off; } } include /etc/nginx/conf.d/*.conf; } ================================================ FILE: files/validator.pm ================================================ package validator; use nginx; use strict; use warnings; sub handler { my $r = shift; my $uri = "/" . ($r->uri =~ /^.*\/small_light[^\/]*\/(.+)$/m)[0]; my $threshold = $r->variable("small_light_maximum_size"); unless ($threshold) { $r->log_error(100, "small_light_maximum_size is not defined!"); $r->internal_redirect($uri); return OK; } my $bad_request = 0; my @params = $r->uri =~ /([a-zA-Z]+=[0-9a-zA-Z]+),?/g; foreach my $param (@params) { my ($key, $value) = split("=", $param); if (grep(/^${key}$/, ("cw", "dw", "ch", "dh"))) { if ($value > $threshold) { $r->log_error(100, "Invalid resize parameter, " . $key . ": " . $value); $bad_request = 1; last; } } } if ($bad_request) { # to avoid ngx_small_light process and return 400 $r->send_http_header; return HTTP_BAD_REQUEST; } $r->internal_redirect($uri); return OK; } 1; __END__ ================================================ FILE: script/bootstrap ================================================ #!/bin/bash # # bootstrap # # Get readly to develop set -e # # Welcome message # echo "" echo " nginx-image-server" echo "" # # Check for VirtualBox # if test ! $(which virtualbox) then echo " x You need to install VirtualBox." echo " You can download it from https://www.virtualbox.org/wiki/Downloads" exit 1 else echo " + VirtualBox found." fi # # Check for Vagrant # if test ! $(which vagrant) then echo " x You need to install Vagrant." echo " You can download it from http://www.vagrantup.com/downloads.html" exit 1 else echo " + Vagrant found." fi # # Install vagrant plugin # if [[ $(vagrant plugin list) =~ dotenv ]] then echo " + Vagrant plugin 'dotenv' found." else echo " x You need to install Vagrant plugin 'dotenv':" echo " $ vagrant plugin install dotenv" exit 1 fi # # Startup instructions # echo "" echo " Good work. We're ready." exit 0 ================================================ FILE: script/build ================================================ #!/bin/bash # # Usage: script/build # Description: build nginx-image-server # set -e docker build -t=quay.io/wantedly/nginx-image-server . ================================================ FILE: script/run ================================================ #!/bin/bash # # Usage: script/run # Description: run nginx-image-server container # Example: # $ script/run-target # $ script/run-target -d # BASE_DIRECTORY=`pwd` MODE="--rm -it" if [ $# -eq 1 ]; then if [ $1 = "-d" ]; then MODE="-d" fi fi cd ${BASE_DIRECTORY} docker kill target > /dev/null 2>&1 || true docker rm target > /dev/null 2>&1 || true docker run \ ${MODE} \ --name nginx-image-server \ -p 80:80 \ -p 8090:8090 \ -v ${BASE_DIRECTORY}/examples:/var/www/nginx/images/ \ -e "SERVER_NAME=${SERVER_NAME}" \ -e "S3_HOST=${S3_HOST}" \ quay.io/wantedly/nginx-image-server:latest ================================================ FILE: script/run-infrataster ================================================ #!/bin/bash # # Usage: script/run-infrataster # Description: run infrataster container # BASE_DIRECTORY=`pwd` cd ${BASE_DIRECTORY}/test/feature docker kill tester > /dev/null 2>&1 || true docker rm tester > /dev/null 2>&1 || true docker run \ --rm \ --name infrataster \ -v $PWD/spec:/test/spec \ -e TARGET_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' nginx-image-server) \ quay.io/wantedly/infrataster:latest ================================================ FILE: script/run-locust ================================================ #!/bin/bash # # Usage: script/run-locust # Description: run tester container # Example: # script/run-locust -f locustfile.py -H localhost --no-web -c 10 -r 1 -n 30 # script/run-locust -f locustfile.py -H localhost # BASE_DIRECTORY=`pwd` LOCUST_ARGS=$@ cd ${BASE_DIRECTORY}/test/performance docker kill locust > /dev/null 2>&1 || true docker rm locust > /dev/null 2>&1 || true docker run \ --rm \ -it \ --name locust \ -p 8089:8089 \ -v ${BASE_DIRECTORY}/test/performance:/test \ quay.io/wantedly/locust:latest \ ${LOCUST_ARGS} ================================================ FILE: script/test ================================================ #!/bin/sh # # Usage: script/cibuild # Description: script to run test # set -e # this script should be run in project root BASE_DIRECTORY=`pwd` SERVER_NAME="image.example.com" echo "==> Building target..." cd ${BASE_DIRECTORY} script/build echo "==> Running nginx-image-server..." docker kill nginx-image-server > /dev/null 2>&1 || true docker rm nginx-image-server > /dev/null 2>&1 || true docker kill infrataster > /dev/null 2>&1 || true docker rm infrataster > /dev/null 2>&1 || true script/run -d echo "==> Running test..." script/run-infrataster echo "==> Cleaning up..." docker kill nginx-image-server > /dev/null 2>&1 || true docker rm nginx-image-server > /dev/null 2>&1 || true docker kill infrataster > /dev/null 2>&1 || true docker rm infrataster > /dev/null 2>&1 || true ================================================ FILE: test/feature/spec/nginx_image_server_spec.rb ================================================ require "spec_helper" describe server(:target) do describe http('http://target/images/example.jpg') do it "responds OK 200" do expect(response.status).to eq(200) end it "responds as 'image/jpeg'" do expect(response.headers['content-type']).to eq("image/jpeg") end end describe http('http://target/local/small_light(dh=600,da=l,ds=s,of=png)/images/example.jpg') do it "responds OK 200" do expect(response.status).to eq(200) end it "responds as 'image/png'" do expect(response.headers['content-type']).to eq("image/png") end end describe http('http://target/local/small_light(dh=600,da=l,ds=s,of=webp)/images/example.jpg') do it "responds OK 200" do expect(response.status).to eq(200) end it "responds as 'image/webp'" do expect(response.headers['content-type']).to eq("image/webp") end end describe http('http://target:8090/status') do it "responds OK 200" do expect(response.status).to eq(200) end it "responds content including 'Active connections'" do expect(response.body).to include("Active connections") end end describe http('http://target/local/small_light(dh=3600,da=l,ds=s,of=webp)/images/example.jpg') do it "responds Bad Request 400" do expect(response.status).to eq(400) end end describe http('http://target/local/small_light(ch=3600,da=l,ds=s,of=webp)/images/example.jpg') do it "responds Bad Request 400" do expect(response.status).to eq(400) end end describe http('http://target/local/small_light(dw=3600,da=l,ds=s,of=webp)/images/example.jpg') do it "responds Bad Request 400" do expect(response.status).to eq(400) end end describe http('http://target/local/small_light(cw=3600,da=l,ds=s,of=webp)/images/example.jpg') do it "responds Bad Request 400" do expect(response.status).to eq(400) end end end ================================================ FILE: test/feature/spec/spec_helper.rb ================================================ require "infrataster/rspec" Infrataster::Server.define( :target, ENV["TARGET_IP"], vagrant: false, ) ================================================ FILE: test/performance/locustfile.py ================================================ from locust import HttpLocust, TaskSet, task import random class MyTaskSet(TaskSet): @task def index(self): dh = random.randint(1, 1200) of = random.choice(["jpg", "gif", "png", "webp"]) self.client.get("/local/small_light(dh=" + str(dh) + ",da=l,ds=s,cc=FFFFFF,of=" + of + ")/images/example.jpg") class WebsiteUser(HttpLocust): task_set = MyTaskSet min_wait=5000 max_wait=9000 ================================================ FILE: wercker.yml ================================================ box: wercker-labs/docker build: steps: - script: name: Check docker version code: | docker -v - script: name: Build quay.io/wantedly/nginx-image-server code: | cd ${WERCKER_SOURCE_DIR} docker build -t quay.io/wantedly/nginx-image-server . - script: name: Run quay.io/wantedly/nginx-image-server code: > script/run -d - script: name: Run tester code: > script/run-infrataster after-steps: - wantedly/pretty-slack-notify: webhook_url: $SLACK_WEBHOOK_URL channel: $SLACK_CHANNEL