Back to Dashboard

openresty

1.29.2.1-alpine
Status
Up to Date
Current Tag
1.29.2.1-alpine
Docker Hub Pulls
1.0K
Stars
0
Size (amd64)
323.9MB
Size (arm64)
309.1MB
Build Lineage
Build Digest 8165e5bdfc5d
Base Image alpine:latest
RESTY_OPENSSL_VERSION 1.1.1w
RESTY_OPENSSL_PATCH_VERSION 1.1.1f
RESTY_PCRE_VERSION 8.45
LUAROCKS_VERSION 3.11.1

Dependency Health

all up to date
2/5 dependencies monitored
Up-to-date dependencies
LUAROCKS_VERSION 3.13.0 NGX_PROXY_CONNECT_VERSION 0.0.7
Unmonitored: RESTY_OPENSSL_VERSION RESTY_OPENSSL_PATCH_VERSION RESTY_PCRE_VERSION

Documentation

OpenResty

High-performance web platform combining Nginx with LuaJIT for dynamic, programmable request handling.

Docker Hub GHCR Build

Quick Start

# Pull from GitHub Container Registry
docker pull ghcr.io/oorabona/openresty:latest

# Pull from Docker Hub
docker pull oorabona/openresty:latest

# Run with custom configuration
docker run -d \
  --name openresty \
  -p 80:80 \
  -p 443:443 \
  -v ./conf.d:/usr/local/openresty/nginx/conf/conf.d:ro \
  -v ./lua:/usr/local/openresty/lualib/app:ro \
  ghcr.io/oorabona/openresty:latest

Features

  • Nginx + LuaJIT: Full Nginx functionality with embedded LuaJIT for dynamic scripting
  • Built from Source: Compiled with optimized configuration, not based on official image
  • Optional Proxy Connect: Includes ngx_http_proxy_connect_module for forward proxy support
  • LuaRocks: Lua package manager included for easy module installation
  • Extensive Modules: Pre-compiled with HTTP/2, SSL, streaming, and dynamic modules
  • Production Ready: Includes healthcheck, non-root worker processes, and security hardening

Usage

Docker Compose

services:
  openresty:
    image: ghcr.io/oorabona/openresty:latest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./conf.d:/usr/local/openresty/nginx/conf/conf.d:ro
      - ./lua:/usr/local/openresty/lualib/app:ro
    read_only: true
    tmpfs:
      - /var/run/openresty
      - /var/cache/nginx
      - /tmp
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    security_opt:
      - no-new-privileges:true

Basic Lua Example

Place your nginx configuration in conf.d/:

# conf.d/default.conf
server {
    listen 80;
    server_name localhost;

    location / {
        content_by_lua_block {
            ngx.say("Hello from OpenResty + Lua!")
        }
    }

    location /api {
        access_by_lua_file /usr/local/openresty/lualib/app/auth.lua;
        proxy_pass http://backend;
    }
}

Custom Lua Modules

Create Lua modules in the lua/ directory:

-- lua/auth.lua
local jwt = require "resty.jwt"

local token = ngx.var.http_authorization
if not token then
    ngx.status = 401
    ngx.say("Missing Authorization header")
    return ngx.exit(401)
end

-- Validate JWT token
local jwt_obj = jwt:verify("secret-key", token)
if not jwt_obj.verified then
    ngx.status = 403
    ngx.say("Invalid token")
    return ngx.exit(403)
end

Installing Lua Packages

# Install a package with LuaRocks
docker exec openresty luarocks install lua-resty-jwt

# List installed packages
docker exec openresty luarocks list

Build Arguments

Argument Description Default
VERSION OpenResty version latest
RESTY_IMAGE_BASE Base image name alpine
RESTY_IMAGE_TAG Base image tag latest
RESTY_VERSION OpenResty version (same as VERSION) ${VERSION}
RESTY_OPENSSL_VERSION OpenSSL version (frozen at 1.1.1) 1.1.1w
RESTY_OPENSSL_PATCH_VERSION OpenSSL patch version 1.1.1f
RESTY_PCRE_VERSION PCRE version (frozen at 8.x) 8.45
RESTY_J Parallel build jobs 4
RESTY_CONFIG_OPTIONS Nginx build options (see Dockerfile)
RESTY_CONFIG_OPTIONS_MORE Additional configure options -j${RESTY_J}
RESTY_LUAJIT_OPTIONS LuaJIT compile options (see Dockerfile)
RESTY_ADD_PACKAGE_BUILDDEPS Additional build dependencies  
RESTY_ADD_PACKAGE_RUNDEPS Additional runtime dependencies  
RESTY_EVAL_PRE_CONFIGURE Commands before configure  
RESTY_EVAL_POST_MAKE Commands after make  
LUAROCKS_VERSION LuaRocks version 3.13.0
ENABLE_HTTP_PROXY_CONNECT Enable proxy connect module false
NGX_PROXY_CONNECT_VERSION Proxy connect module version 0.0.7

Environment Variables

Variable Description Default
PATH Includes OpenResty binaries /usr/local/openresty/…

OpenResty uses standard Nginx environment variables:

  • Configure via nginx.conf or environment-specific conf files
  • Use envsubst in config files for dynamic variables
  • See Nginx documentation for configuration options

Volumes

Path Description
/usr/local/openresty/nginx/conf/conf.d Nginx configuration files (mount read-only)
/usr/local/openresty/lualib/app Custom Lua modules (mount read-only)
/var/run/openresty Runtime files (use tmpfs)
/var/cache/nginx Cache directory (use tmpfs)
/var/log/nginx Log files (logs to stdout/stderr by default)

Ports

Port Protocol Description
80 HTTP Default HTTP port
443 HTTPS Default HTTPS port

Configure custom ports in your nginx configuration. For non-privileged operation, use ports > 1024.

Security

Process Security

  • Master Process: Runs as root (required for binding to ports 80/443)
  • Worker Processes: Run as non-root nginx user (uid 101, gid 101)
  • No Shell: nginx user has /sbin/nologin shell
  • Signal Handling: Uses SIGQUIT for clean shutdown

Runtime Hardening

The included docker-compose.yml demonstrates security best practices:

services:
  openresty:
    image: ghcr.io/oorabona/openresty:latest
    read_only: true              # Immutable filesystem
    tmpfs:
      - /var/run/openresty       # Writable runtime directory
      - /var/cache/nginx         # Writable cache directory
      - /tmp                     # Writable temp directory
    cap_drop:
      - ALL                      # Drop all capabilities
    cap_add:
      - NET_BIND_SERVICE         # Only allow binding privileged ports
    security_opt:
      - no-new-privileges:true   # Prevent privilege escalation

Non-Privileged Port Alternative

For maximum security without root at all:

services:
  openresty:
    image: ghcr.io/oorabona/openresty:latest
    user: "101:101"              # Run as nginx:nginx
    read_only: true
    tmpfs:
      - /var/run/openresty
      - /var/cache/nginx
      - /tmp
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    ports:
      - "8080:8080"
      - "8443:8443"

Note: Requires nginx configuration to listen on 8080/8443 instead of 80/443.

Healthcheck

Built-in healthcheck verifies OpenResty is responding:

HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
    CMD curl -f http://localhost/nginx_status || exit 1

Ensure your nginx configuration includes a status endpoint:

location /nginx_status {
    stub_status on;
    access_log off;
    allow 127.0.0.1;
    deny all;
}

Dependencies

This container includes the following pinned dependencies:

Dependency Version Monitoring Status Notes
Alpine Linux latest Active Base image
OpenResty (from version.sh) Active Main application
OpenSSL 1.1.1w Frozen (EOL) OpenSSL 1.1.1 series ended 2023-09-11
PCRE 8.45 Frozen (EOL) PCRE 8.x is legacy, PCRE2 not used
LuaRocks 3.13.0 Active Lua package manager
ngx_http_proxy_connect_module 0.0.7 Active Optional forward proxy support

Note on frozen dependencies:

  • OpenSSL 1.1.1w: Intentionally frozen at the final 1.1.1 release. OpenResty requires specific patches for this version. Migration to OpenSSL 3.x requires upstream OpenResty changes.
  • PCRE 8.45: Legacy PCRE library (not PCRE2). OpenResty builds against PCRE 8.x for compatibility.

These frozen versions receive security backports through OpenResty’s patching mechanism.

Architecture

Build Process

  1. Bootstrap: Downloads and compiles OpenSSL 1.1.1 with OpenResty patches
  2. PCRE Compilation: Builds PCRE with JIT support
  3. Optional Module: Downloads ngx_http_proxy_connect_module if enabled
  4. OpenResty Build: Configures and compiles OpenResty with all modules
  5. LuaRocks Installation: Installs Lua package manager
  6. Cleanup: Removes build dependencies to minimize image size

Included Nginx Modules

Core HTTP Modules:

  • http_ssl_module - HTTPS support
  • http_v2_module - HTTP/2 protocol
  • http_realip_module - Client IP from proxy headers
  • http_addition_module - Add text before/after responses
  • http_sub_module - Response substitution
  • http_dav_module - WebDAV methods
  • http_flv_module - FLV streaming
  • http_mp4_module - MP4 streaming
  • http_gunzip_module - Decompress responses
  • http_gzip_static_module - Serve pre-compressed files
  • http_auth_request_module - External authentication
  • http_random_index_module - Random directory index
  • http_secure_link_module - Signed URL validation
  • http_slice_module - Range request slicing
  • http_stub_status_module - Basic status page

Dynamic Modules:

  • http_geoip_module - Geolocation based on IP
  • http_image_filter_module - Image transformation
  • http_xslt_module - XSLT transformations

Stream Modules:

  • stream_core_module - TCP/UDP load balancing
  • stream_ssl_module - TLS for stream

Mail Modules:

  • mail_core_module - Mail proxy
  • mail_ssl_module - SMTP/IMAP/POP3 SSL

Directory Structure

/usr/local/openresty/
├── bin/
│   ├── openresty           # OpenResty binary
│   ├── resty               # Resty CLI
│   └── restydoc            # Documentation viewer
├── luajit/
│   └── bin/
│       ├── luajit          # LuaJIT interpreter
│       └── luarocks        # Lua package manager
├── lualib/                 # Lua libraries
│   ├── resty/              # OpenResty Lua modules
│   └── app/                # Custom modules (mount here)
├── nginx/
│   ├── conf/
│   │   ├── nginx.conf      # Main configuration
│   │   └── conf.d/         # Additional configs (mount here)
│   ├── html/               # Default web root
│   └── logs/               # Logs (symlinked to stdout/stderr)
├── openssl/                # OpenSSL libraries
└── pcre/                   # PCRE libraries

Common Use Cases

API Gateway

upstream backend {
    server api1:3000;
    server api2:3000;
    keepalive 32;
}

server {
    listen 80;

    location /api/v1 {
        access_by_lua_block {
            -- Rate limiting
            local limit = require "resty.limit.req"
            local lim = limit.new("limit_store", 100, 50)
            local key = ngx.var.remote_addr
            local delay, err = lim:incoming(key, true)
            if not delay then
                if err == "rejected" then
                    return ngx.exit(429)
                end
            end
        }

        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

Web Application Firewall

-- lua/waf.lua
local rules = {
    sql_injection = [[(\%27)|(\')|(\-\-)|(\%23)|(#)]],
    xss = [[(\%3C)|(<)|(\%3E)|(>)|(\%3c)|(\%3e)]],
}

local uri = ngx.var.uri
local args = ngx.var.args or ""

for rule_name, pattern in pairs(rules) do
    if string.match(uri, pattern) or string.match(args, pattern) then
        ngx.log(ngx.ERR, "WAF: Blocked ", rule_name, " attempt")
        return ngx.exit(403)
    end
end

Caching Proxy

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=cache:10m max_size=1g inactive=60m;

server {
    listen 80;

    location / {
        proxy_cache cache;
        proxy_cache_valid 200 60m;
        proxy_cache_valid 404 1m;
        proxy_cache_key "$scheme$request_method$host$request_uri";
        proxy_cache_bypass $http_cache_control;
        add_header X-Cache-Status $upstream_cache_status;

        proxy_pass http://origin;
    }
}

Dynamic Load Balancing

-- lua/balancer.lua
local balancer = require "ngx.balancer"
local redis = require "resty.redis"

-- Get healthy backends from Redis
local red = redis:new()
red:connect("redis", 6379)
local backends = red:smembers("healthy_backends")

-- Round-robin selection
local current = ngx.shared.balance:incr("counter", 1, 0)
local index = (current % #backends) + 1
local backend = backends[index]

-- Set upstream server
local ok, err = balancer.set_current_peer(backend)
if not ok then
    ngx.log(ngx.ERR, "failed to set peer: ", err)
    return ngx.exit(500)
end

Performance Tips

  • Connection Pooling: Use keepalive upstream connections
  • Lua Shared Dictionaries: Cache data across workers with lua_shared_dict
  • LuaJIT Optimization: Profile code with -jdump for hotspots
  • Worker Processes: Set to number of CPU cores
  • Sendfile: Enable for static file serving
  • TCP Nopush: Reduce network overhead
  • Gzip: Compress responses (or use gzip_static)

Version Management

# Check current version
./version.sh

# Check latest upstream version
./version.sh latest

# Output JSON for automation
./version.sh --json

Building Locally

# From repository root
./make build openresty

# With specific version
./make build openresty 1.25.3.2

# With proxy connect module
docker build \
  --build-arg ENABLE_HTTP_PROXY_CONNECT=true \
  -t openresty:latest .