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
[](https://quay.io/repository/wantedly/nginx-image-server)
[](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=<YOUR-BUCKET-NAME>.s3.amazonaws.com" \
quay.io/wantedly/nginx-image-server:latest
```
Then you can try image-processing by accessing
* **Images in S3**: `http://<YOUR-SERVER.com>/small_light(dh=400,da=l,ds=s)/<PATH-TO-IMAGE-IN-S3>`
* **Images in Local**: `http://<YOUR-SERVER.com>/local/small_light(dh=400,da=l,ds=s)/images/example.jpg`
And `http://<YOUR-SERVER.com>: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
[](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
[](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 <MODE>
# 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 <LOCUST_ARGS>
# 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
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
SYMBOL INDEX (3 symbols across 1 files)
FILE: test/performance/locustfile.py
class MyTaskSet (line 4) | class MyTaskSet(TaskSet):
method index (line 6) | def index(self):
class WebsiteUser (line 11) | class WebsiteUser(HttpLocust):
Condensed preview — 22 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (31K chars).
[
{
"path": ".dockerignore",
"chars": 23,
"preview": "*\n!Dockerfile\n!files/*\n"
},
{
"path": ".gitignore",
"chars": 49,
"preview": ".env\n.DS_Store\nlocustfile.pyc\nuser-data\n.vagrant\n"
},
{
"path": ".travis.yml",
"chars": 360,
"preview": "sudo: required\nservices:\n- docker\nscript:\n- docker -v\n- docker build -t quay.io/wantedly/nginx-image-server .\n- script/r"
},
{
"path": "Dockerfile",
"chars": 2836,
"preview": "FROM ubuntu:14.04\n\nENV NGINX_VERSION 1.10.0\nENV NGX_SMALL_LIGHT_VERSION 0.9.1\nENV IMAGEMAGICK_VERSION 6.8.6-8\n\n# Install"
},
{
"path": "LICENSE",
"chars": 1086,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2014-2016 Wantedly, Inc.\n\nPermission is hereby granted, free of charge, to any pers"
},
{
"path": "README.md",
"chars": 3715,
"preview": "# Nginx Image Server\n[ do\n describe http('http://target/images/example.jpg') do\n it \"respon"
},
{
"path": "test/feature/spec/spec_helper.rb",
"chars": 108,
"preview": "require \"infrataster/rspec\"\n\nInfrataster::Server.define(\n :target,\n ENV[\"TARGET_IP\"],\n vagrant: false,\n)\n"
},
{
"path": "test/performance/locustfile.py",
"chars": 418,
"preview": "from locust import HttpLocust, TaskSet, task\nimport random\n\nclass MyTaskSet(TaskSet):\n @task\n def index(self):\n "
},
{
"path": "wercker.yml",
"chars": 630,
"preview": "box: wercker-labs/docker\nbuild:\n steps:\n - script:\n name: Check docker version\n code: |\n dock"
}
]
About this extraction
This page contains the full source code of the wantedly/nginx-image-server GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 22 files (27.8 KB), approximately 8.3k tokens, and a symbol index with 3 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.