⚠️ No Official Docker Image
H2O does not have an official Docker image. Use community-maintained images or build your own.
⚠️ Version Policy
H2O no longer uses version tagging since January 2020. The master branch is considered stable. Community images are built from the master branch.
This guide uses community-maintained Docker images to run H2O. This is a recommended installation method for containerized deployments, as it provides up-to-date builds from the master branch.
| Image | Maintainer | Version | Last Update |
|---|---|---|---|
micrograils/h2o |
micrograils | 2.3.0-DEV (master) | ~3 months ago |
| Build your own | Self | Latest master | On-demand |
For Docker installation, see Docker.
mkdir -p /opt/h2o
cd /opt/h2o
# docker-compose.yml
services:
h2o:
image: micrograils/h2o:latest
container_name: h2o
ports:
- "80:80" # HTTP
- "443:443" # HTTPS
- "8443:8443/udp" # HTTP/3 QUIC (optional)
volumes:
- ./config:/etc/h2o # Configuration
- ./www:/var/www # Web content
- ./logs:/var/log/h2o # Logs
restart: unless-stopped
networks:
- h2o-net
networks:
h2o-net:
driver: bridge
⚠️ HTTP/3 QUIC Note: UDP port 8443 is optional. Enable only if your use case benefits from QUIC protocol.
mkdir -p config www logs
# config/h2o.conf
listen:
port: 80
hosts:
"default":
paths:
"/":
file.dir: /var/www
file.index: [index.html]
cat > www/index.html << 'EOF'
<!DOCTYPE html>
<html>
<head><title>H2O Server</title></head>
<body>
<h1>H2O is running</h1>
<p>HTTP/1, HTTP/2, HTTP/3 (QUIC) support enabled</p>
</body>
</html>
EOF
docker compose up -d
# Check container status
docker compose ps
# Test HTTP response
curl -I http://localhost
# Check logs
docker compose logs h2o
Open http://SERVER_IP in your browser.
For maximum control, build your own Docker image from the H2O master branch.
FROM alpine:latest
LABEL maintainer="Your Name <your@email.com>"
LABEL description="H2O - HTTP/1, HTTP/2, HTTP/3 Server"
# Install build dependencies
RUN apk add --no-cache \
build-base \
cmake \
pkgconf \
openssl-dev \
zlib-dev \
git \
perl
# Clone H2O source
RUN git clone --recurse-submodules https://github.com/h2o/h2o.git /usr/src/h2o
# Build H2O
WORKDIR /usr/src/h2o
RUN mkdir -p build && \
cd build && \
cmake -DCMAKE_BUILD_TYPE=Release .. && \
make -j$(nproc) && \
make install
# Create runtime user
RUN addgroup -S h2o && adduser -S h2o -G h2o
# Create directories
RUN mkdir -p /etc/h2o /var/www /var/log/h2o /var/lib/h2o && \
chown -R h2o:h2o /etc/h2o /var/www /var/log/h2o /var/lib/h2o
# Copy default configuration
COPY << 'EOF' /etc/h2o/h2o.conf
listen:
port: 80
hosts:
"default":
paths:
"/":
file.dir: /var/www
file.index: [index.html]
EOF
# Expose ports
EXPOSE 80 443 8443/udp
# Run as non-root user
USER h2o
WORKDIR /var/www
# Start H2O
CMD ["h2o", "-c", "/etc/h2o/h2o.conf", "-m", "worker"]
# Build the image
docker build -t h2o:latest .
# Run the container
docker run -d \
--name h2o \
-p 80:80 \
-p 443:443 \
-p 8443:8443/udp \
-v $(pwd)/config:/etc/h2o \
-v $(pwd)/www:/var/www \
h2o:latest
# config/h2o.conf (HTTPS)
listen:
port: 443
ssl:
certificate-file: /etc/h2o/certs/server.crt
key-file: /etc/h2o/certs/server.key
hosts:
"example.com":
paths:
"/":
file.dir: /var/www
services:
h2o:
image: micrograils/h2o:latest
volumes:
- ./config:/etc/h2o
- ./certs:/etc/h2o/certs:ro # Read-only certificates
- ./www:/var/www
# config/h2o.conf (HTTP/3)
listen:
port: 443
ssl:
certificate-file: /etc/h2o/certs/server.crt
key-file: /etc/h2o/certs/server.key
http3: true
hosts:
"example.com":
paths:
"/":
file.dir: /var/www
docker compose logs -f h2o
docker compose restart
docker compose down
docker compose pull
docker compose up -d
# Check H2O version
docker compose exec h2o h2o --version
# Test configuration
docker compose exec h2o h2o -t -c /etc/h2o/h2o.conf
# Access shell (if available)
docker compose exec h2o /bin/sh
⚠️ Security Warning: Keep H2O updated by pulling latest images regularly.
Run as Non-Root User
h2o userdocker compose exec h2o whoamiRestrict Network Exposure
ports:
- "127.0.0.1:80:80" # Localhost only
Use TLS Termination
Read-Only Volumes
volumes:
- ./certs:/etc/h2o/certs:ro
- ./config:/etc/h2o:ro
Resource Limits
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
HTTP/3 Considerations
See h2o Security and H2O Hardening for additional guidance.
| Issue | Solution |
|---|---|
| Container fails to start | Check logs: docker compose logs h2o |
| Configuration errors | Validate: docker compose exec h2o h2o -t -c /etc/h2o/h2o.conf |
| Port already in use | Change host port mapping or stop conflicting service |
| HTTP/3 not working | Ensure UDP port is open, check firewall rules |
| Certificate errors | Verify certificate paths and permissions |
Deploying H2O in containers for production? Our consulting covers:
Get expert help: office@linux-server-admin.com | Contact Page