diff --git a/.github/workflows/build_image.yml b/.github/workflows/build_image.yml new file mode 100644 index 00000000..813e69c0 --- /dev/null +++ b/.github/workflows/build_image.yml @@ -0,0 +1,83 @@ +name: build_image + +on: + push: + branches: ["iotex-stg"] + tags: ["v*.*.*"] + +env: + REGISTRY: ghcr.io + REPOSITORY_URI_WEB: iotex-project/safe-transaction-web + REPOSITORY_URI_NGINX: iotex-project/safe-transaction-nginx + +jobs: + build_docker_image: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + permissions: + contents: read + packages: write + id-token: write + + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + + - name: Setup Docker and Colima + if: startsWith(matrix.os, 'macos-latest') == true + run: | + brew install docker colima + colima start + + - name: Setup Docker buildx + uses: docker/setup-buildx-action@v2 + + - name: Log into registry ${{ env.REGISTRY }} + if: github.event_name != 'pull_request' + uses: docker/login-action@v2 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract Docker metadata + id: meta-web + uses: docker/metadata-action@v4 + with: + images: | + ${{ env.REGISTRY }}/${{ env.REPOSITORY_URI_WEB }} + + + - name: Build and push Docker image web + id: build-and-push-web + uses: docker/build-push-action@v4 + with: + platforms: linux/amd64 + context: . + file: ./Dockerfile + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta-web.outputs.tags }} + labels: ${{ steps.meta-web.outputs.labels }} + + + - name: Extract Docker metadata + id: meta-nginx + uses: docker/metadata-action@v4 + with: + images: | + ${{ env.REGISTRY }}/${{ env.REPOSITORY_URI_NGINX }} + - name: Build and push Docker image nginx + id: build-and-push-nginx + uses: docker/build-push-action@v4 + with: + context: . + platforms: linux/amd64 + file: ./nginx.Dockerfile + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta-nginx.outputs.tags }} + labels: ${{ steps.meta-nginx.outputs.labels }} diff --git a/nginx.Dockerfile b/nginx.Dockerfile new file mode 100644 index 00000000..cb15978b --- /dev/null +++ b/nginx.Dockerfile @@ -0,0 +1,14 @@ +FROM nginx:1.25.3-alpine + +RUN apk upgrade --update-cache --available && apk add openssl && rm -rf /var/cache/apk/* + +RUN openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout /etc/nginx/self.key -out /etc/nginx/self.crt -subj "/CN=*" + +COPY nginx.conf /etc/nginx/nginx.conf + +#COPY version.txt /usr/share/nginx/html/version.txt + +STOPSIGNAL SIGTERM + +CMD ["nginx", "-g", "daemon off;"] + diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 00000000..8e07e897 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,118 @@ +worker_processes auto; +worker_rlimit_nofile 10000; +worker_shutdown_timeout 65s; + +events { + worker_connections 5000; + accept_mutex off; + use epoll; + multi_accept on; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + + # Real IP + set_real_ip_from 127.0.0.1; + set_real_ip_from 10.0.0.0/8; + set_real_ip_from 172.16.0.0/12; + set_real_ip_from 192.168.0.0/16; + real_ip_header X-Forwarded-For; + real_ip_recursive on; + + # Logs + map "$time_local:$msec" $time_local_ms { ~(^\S+)(\s+\S+):\d+\.(\d+)$ $1.$3$2; } + + log_format main escape=json + '$remote_addr - $realip_remote_addr - $request_time - [$time_local_ms] - $msec - ' + '$http_x_amzn_trace_id - $request_id - $connection-$connection_requests - ' + '$scheme - $host - $server_port - $ssl_protocol - $ssl_cipher - ' + '$request_method - $request_uri - $server_protocol - $status - $request_completion - ' + '$bytes_sent - $request_length - "$http_referer" - "$http_user_agent" - ' + '$proxy_host - "$upstream_addr" - "$upstream_status" - "$upstream_connect_time" - "$upstream_response_time" '; + # '$proxy_host - "$upstream_addr" - "$upstream_status" - "$upstream_connect_time" - "$upstream_response_time" - "$request_body" '; + + access_log /var/log/nginx/access.log main; + error_log /var/log/nginx/error.log info; + + # SSL + ssl_certificate /etc/nginx/self.crt; + ssl_certificate_key /etc/nginx/self.key; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers HIGH:!aNULL:!MD5; + + # Compression + gzip on; + gzip_min_length 1000; + gzip_comp_level 3; + gzip_types text/plain text/css application/json application/javascript application/x-javascript text/javascript text/xml application/xml application/rss+xml application/atom+xml application/rdf+xml; + + # Timeouts + keepalive_timeout 10s; + client_header_timeout 10s; + client_body_timeout 30s; + send_timeout 65s; + + # Request + client_max_body_size 100M; + + # Response + charset utf-8; + + # Proxy + proxy_connect_timeout 65s; + proxy_send_timeout 65s; + proxy_read_timeout 65s; + + proxy_buffering off; + proxy_buffers 8 64k; + proxy_buffer_size 64k; + proxy_busy_buffers_size 128k; + + proxy_http_version 1.1; + proxy_intercept_errors off; + + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + #proxy_set_header X-Forwarded-Proto $scheme; + # $http_x_forwarded_proto (passed by AWS ALB) stores the real protocol used by end user + proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; + proxy_set_header X-Forwarded-Host $server_name; + proxy_set_header X-Forwarded-Server $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $host; + proxy_set_header Connection ""; + add_header Front-End-Https on; + add_header X-Robots-Tag "noindex,nofollow,noarchive"; + proxy_redirect off; + + # Upstreams + upstream app_server { + server unix:/nginx/gunicorn.socket fail_timeout=0; + keepalive 32; + } + + # Servers + server { + listen 8000 deferred default_server; + listen 8443 ssl http2 deferred default_server; + + # Version + # location /version.txt { root /usr/share/nginx/html; } + + # Static + location /static { + alias /nginx/staticfiles; + expires 365d; + } + + # App + location / { + proxy_pass http://app_server; + } + } +}