Skip to content

Commit 6b83872

Browse files
authored
Merge pull request #85 from adobejmong/ETHOS-36876
feat(ETHOS-36876): Add new Ubuntu 22.04, Replace nginx installation, Add njs module (ubuntu only)
2 parents 767874f + 69744ff commit 6b83872

29 files changed

+538
-119
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ jobs:
1111
matrix:
1212
props:
1313
- Dockerfile: Dockerfile
14+
- Dockerfile: Dockerfile-ubuntu-22.04
1415
# - Dockerfile: Dockerfile-alpine
1516
# - Dockerfile: Dockerfile-centos
1617
platform:

.github/workflows/publish.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,14 @@ jobs:
1616
# This is the default variant-less distribution (ex. 3.2.1)
1717
- Dockerfile: Dockerfile
1818
# Variant distributions below all have semantic versions + suffix (ex. 3.2.1-alpine)
19+
# Alpine is deprecated
1920
- Dockerfile: Dockerfile-alpine
2021
suffix: alpine
22+
# CentOS is deprecated
2123
- Dockerfile: Dockerfile-centos
2224
suffix: centos
25+
- Dockerfile: Dockerfile-ubuntu-22.04
26+
suffix: ubuntu-22.04
2327
steps:
2428
-
2529
name: Checkout

Dockerfile-alpine

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
################################################################################
2+
# The AlpineOS flavor is DEPRECATED and will be removed in a future release
3+
# Please stop using this variant and use the Ubuntu flavor instead
4+
################################################################################
15
FROM behance/docker-base:5.0.1-alpine
26

37
# Use in multi-phase builds, when an init process requests for the container to gracefully exit, so that it may be committed

Dockerfile-centos

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
################################################################################
2+
# The CentOS flavor is DEPRECATED and will be removed in a future release
3+
# Please stop using this variant and use the Ubuntu flavor instead
4+
################################################################################
15
FROM behance/docker-base:5.0.1-centos-7
26

37
# Use in multi-phase builds, when an init process requests for the container to gracefully exit, so that it may be committed

Dockerfile-ubuntu-22.04

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
FROM behance/docker-base:5.1.0-ubuntu-22.04 AS base
2+
3+
### Stage 1 - add/remove packages ###
4+
5+
# Ensure scripts are available for use in next command
6+
COPY ./container/root/scripts/* /scripts/
7+
8+
# Env vars used during the build process
9+
ENV CONTAINER_PORT=8080 \
10+
CONF_NGINX_SITE="/etc/nginx/sites-available/default" \
11+
NOT_ROOT_USER=www-data
12+
13+
# - Update security packages, plus ca-certificates required for https
14+
# - Install nginx
15+
# - Install njs
16+
RUN /bin/bash -e /security_updates.sh && \
17+
/bin/bash -e /scripts/install_nginx.sh && \
18+
/bin/bash -e /scripts/install_njs.sh
19+
20+
# Overlay the root filesystem from this repo
21+
COPY --chown=www-data ./container/root /
22+
23+
# Set nginx to listen on defined port
24+
#
25+
# NOTE: order of operations is important, new config had to already installed
26+
# from repo (above)
27+
#
28+
# - Make temp directory for .nginx runtime files
29+
# - Fix woff mime type support
30+
# - Set permissions to allow image to be run under a non root user
31+
RUN sed -i "s/listen [0-9]*;/listen ${CONTAINER_PORT};/" $CONF_NGINX_SITE && \
32+
mkdir /tmp/.nginx && \
33+
/bin/bash -e /scripts/fix_woff_support.sh && \
34+
/bin/bash -e /scripts/set_permissions.sh
35+
36+
# Clean up
37+
RUN /bin/bash -e /scripts/cleanup.sh && \
38+
/bin/bash -e /clean.sh
39+
40+
### Stage 2 --- collapse layers ###
41+
42+
FROM scratch
43+
COPY --from=base / .
44+
45+
# Using a non-privileged port to prevent having to use setcap internally
46+
EXPOSE ${CONTAINER_PORT}
47+
48+
# Env vars used during runtime
49+
ENV CONTAINER_ROLE=web \
50+
CONTAINER_PORT=8080 \
51+
CONF_NGINX_SITE="/etc/nginx/sites-available/default" \
52+
CONF_NGINX_SERVER="/etc/nginx/nginx.conf" \
53+
NOT_ROOT_USER=www-data
54+
55+
# Use in multi-phase builds, when an init process requests for the container
56+
# to gracefully exit, so that it may be committed
57+
#
58+
# Used with alternative CMD (worker.sh), leverages supervisor to maintain
59+
# long-running processes
60+
ENV SIGNAL_BUILD_STOP=99 \
61+
S6_BEHAVIOUR_IF_STAGE2_FAILS=2 \
62+
S6_KILL_FINISH_MAXTIME=55000 \
63+
S6_KILL_GRACETIME=3000
64+
65+
RUN goss -g /tests/ubuntu/nginx.goss.yaml validate && \
66+
/aufs_hack.sh
67+
68+
# NOTE: intentionally NOT using s6 init as the entrypoint
69+
# This would prevent container debugging if any of those service crash
70+
CMD ["/bin/bash", "/run.sh"]

Makefile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
.PHONY: all
2+
3+
IMAGE_NAME ?= docker-nginx
4+
OS_FAMILY ?= ubuntu-22.04
5+
PLATFORM ?= linux/amd64
6+
VERSION ?= test
7+
8+
# Create
9+
IMAGE_TAG ?= $(VERSION)-$(OS_FAMILY)
10+
11+
default: build
12+
13+
build:
14+
docker build --platform $(PLATFORM) -t $(IMAGE_NAME):$(IMAGE_TAG) -f Dockerfile-$(OS_FAMILY) .
15+
16+
clean-room:
17+
docker system prune -a -f --volumes

README.md

Lines changed: 24 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -4,133 +4,39 @@ https://hub.docker.com/r/behance/docker-nginx/tags/
44

55
Provides base OS, patches and stable nginx for quick and easy spinup.
66

7-
- Ubuntu used by default
8-
- Alpine builds available tagged as `-alpine`
9-
- Centos builds available tagged as `-centos`
7+
- Ubuntu 22.04 used by default
8+
- Alpine builds available tagged as `-alpine` **DEPRECATED**
9+
- Centos builds available tagged as `-centos` **DEPRECATED**
1010

11-
12-
[S6](https://github.com/just-containers/s6-overlay) process supervisor is used for `only` for zombie reaping (as PID 1), boot coordination, and termination signal translation
11+
[S6](https://github.com/just-containers/s6-overlay) process supervisor is used
12+
for `only` for zombie reaping (as PID 1), boot coordination, and termination
13+
signal translation
1314

1415
[Goss](https://github.com/aelsabbahy/goss) is used for build-time testing.
1516

16-
See parent(s) [docker-base](https://github.com/behance/docker-base) for additional configuration
17-
18-
19-
### Expectations
20-
21-
- Applications must copy their html/app into the `/var/www/html` folder
22-
- Any new script/file that needs to be added must be given proper permissions/ownership to the non root user through `container/root/scripts/set_permissions.sh`. This is to ensure that the image can be run under a non root user.
23-
- NOTE: Nginx is exposed and bound to an unprivileged port, `8080`
24-
25-
26-
### Container Security
27-
28-
See parent [configuration](https://github.com/behance/docker-base#security)
29-
30-
31-
### HTTPS usage
32-
33-
To enable this container to serve HTTPS over its primary exposed port:
34-
- `SERVER_ENABLE_HTTPS` environment variable must be `true`
35-
- Certificates must be present in `/etc/nginx/certs` under the following names:
36-
- `ca.crt`
37-
- `ca.key`
38-
- Additionally, they must be marked read-only (0600)
39-
40-
#### Local development usage
41-
42-
To generate a self-signed certificate (won't work in most browsers):
43-
```
44-
openssl genrsa -out ca.key 2048
45-
openssl req -new -key ca.key -out ca.csr -subj '/CN=localhost'
46-
openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crt
47-
```
48-
49-
Run the image in background, bind external port (443), flag HTTPS enabled, mount certificate:
50-
```
51-
docker run \
52-
-d
53-
-p 443:8080 \
54-
-e SERVER_ENABLE_HTTPS=true \
55-
-v {directory-containing-ca.crt-and-ca.key}:/etc/nginx/certs:ro
56-
behance/docker-nginx
57-
```
58-
59-
Test
60-
```
61-
curl -k -vvv https://{your-docker-machine-ip}
62-
```
63-
64-
65-
### Environment Variables
66-
67-
Variable | Example | Description
68-
--- | --- | ---
69-
SERVER_MAX_BODY_SIZE | SERVER_MAX_BODY_SIZE=4M | Allows the downstream application to specify a non-default `client_max_body_size` configuration for the `server`-level directive in `/etc/nginx/sites-available/default`
70-
SERVER_INDEX | SERVER_INDEX index.html index.html index.php | Changes the default pages to hit for folder and web roots
71-
SERVER_APP_NAME | SERVER_APP_NAME='view' | Gets appended to the default logging format
72-
SERVER_GZIP_OPTIONS | SERVER_GZIP_OPTIONS=1 | Allows default set of static content to be served gzipped
73-
SERVER_SENDFILE | SERVER_SENDFILE=off | Allows runtime to specify value of nginx's `sendfile` (default, on)
74-
SERVER_ENABLE_HTTPS | SERVER_ENABLE_HTTPS=true | Enable encrypted transmission using certificates
75-
SERVER_KEEPALIVE | SERVER_KEEPALIVE=30 | Define HTTP 1.1's keepalive timeout
76-
SERVER_WORKER_PROCESSES | SERVER_WORKER_PROCESSES=4 | Set to the number of cores in the machine, or the number of cores allocated to container
77-
SERVER_WORKER_CONNECTIONS | SERVER_WORKER_CONNECTIONS=2048 | Sets up the number of connections for worker processes
78-
SERVER_CLIENT_HEADER_BUFFER_SIZE | SERVER_CLIENT_HEADER_BUFFER_SIZE=16k | [docs](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_header_buffer_size)
79-
SERVER_LARGE_CLIENT_HEADER_BUFFERS | SERVER_LARGE_CLIENT_HEADER_BUFFERS=8 16k | [docs](http://nginx.org/en/docs/http/ngx_http_core_module.html#large_client_header_buffers)
80-
SERVER_CLIENT_BODY_BUFFER_SIZE | SERVER_CLIENT_BODY_BUFFER_SIZE=128k | [docs](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_buffer_size)
81-
SERVER_LOG_MINIMAL | SERVER_LOG_MINIMAL=1 | Minimize the logging format, appropriate for development environments
82-
S6_KILL_FINISH_MAXTIME | S6_KILL_FINISH_MAXTIME=55000 | The maximum time (in ms) a script in /etc/cont-finish.d could take before sending a KILL signal to it. Take into account that this parameter will be used per each script execution, it's not a max time for the whole set of scripts. This value has a max of 65535 on Alpine variants.
83-
S6_KILL_GRACETIME | S6_KILL_GRACETIME=500 | Wait time (in ms) for S6 finish scripts before sending kill signal
84-
85-
86-
### Startup/Runtime Modification
87-
88-
- Environment variables are used to drive nginx configuration at runtime
89-
- See [here](https://github.com/behance/docker-base#startupruntime-modification) for more advanced options
90-
91-
### Shutdown Behavior
92-
93-
Graceful shutdown is handled as part of the [existing](https://github.com/behance/docker-base#shutdown-behavior) S6 termination process, using a `/etc/cont-finish.d` script.
94-
Nginx will attempt to drain active workers, while rejecting new connections. The drain timeout is controlled by `S6_KILL_FINISH_MAXTIME`, which corresponds to the length of time the supervisor will wait for the script to run during shutdown. This value defaults to 55s, which deliberately `less` than an downstream load balancers default max connection length (60s). Each upstream's timeout must be less than the downstream, for sanity and lack of timing precision.
95-
96-
### Long-running processes (workers + crons)
97-
98-
- See parent [configuration](https://github.com/behance/docker-base#long-running-processes-workers--crons) on reusing container for other purposes.
99-
100-
101-
### Container Organization
102-
103-
Besides the instructions contained in the Dockerfile, the majority of this
104-
container's use is in configuration and process. The `./container/root` repo directory is overlayed into a container during build. Adding additional files
105-
to the folders in there will be present in the final image.
106-
107-
Nginx is currently set up as an S6 service in `/etc/services-available/nginx`, during default environment conditions, it will symlink itself to be supervised under `/etc/services.d/nginx`. When running under worker entrypoint (`worker.sh`), it will not be S6's `service.d` folder to be supervised.
108-
109-
110-
### Release Management
111-
112-
Github actions provide the machinery for testing (ci.yaml) and producing tags distributed through Docker Hub (publish.yaml). Testing will confirm that `nginx` is able to serve content in various configurations, but also that it can terminate TLS with self-signed certificates. Once a tested and approved PR is merged, simply cutting a new semantically-versioned tag will generate the following matrix of tagged builds:
113-
- `[major].[minor].[patch](?-variant)`
114-
- `[major].[minor](?-variant)`
115-
- `[major](?-variant)`
116-
Platform support is available for architectures:
117-
- `linux/arm64`
118-
- `linux/amd64`
17+
See parent(s) [docker-base](https://github.com/behance/docker-base) for
18+
additional configuration
11919

120-
To add new variant based on a new Dockerfile, add an entry to `matrix.props` within `./github/workflows` YAML files.
20+
# Expectations
12121

122-
### Github Actions: Simulation
22+
NOTE: Nginx is exposed and bound to an unprivileged port, `8080`
12323

124-
docker-nginx uses Github Actions for CI/CD. Simulated workflows can be achieved locally with `act`. All commands must be executes from repository root.
24+
* Applications must copy their html/app into the `/var/www/html` folder
12525

126-
Pre-reqs: tested on Mac
127-
1. [Docker Desktop](https://www.docker.com/products/docker-desktop)
128-
1. [act](https://github.com/nektos/act)
26+
* Any new script/file that needs to be added must be given proper permissions /
27+
ownership to the non root user through `container/root/scripts/set_permissions.sh`.
28+
This is to ensure that the image can be run under a non root user.
12929

130-
Pull request simulation: executes successfully, but only on ARM devices (ex. Apple M1). ARM emulation through QEMU on X64 machines does not implement the full kernel functionality required by nginx at this time.
131-
- `act pull_request`
30+
# Quick Start
13231

133-
Publish simulation: executes, but fails (intentionally) without credentials
134-
- `act`
32+
See [Quick Start](docs/quick_start.md)
13533

34+
# Docs
13635

36+
* [Container Organization](docs/container_organization.md)
37+
* [Container Security](docs/container_security.md)
38+
* [Environment Variables](docs/env_vars.md)
39+
* [Long-running processes (workers + crons)](docs/long_running.md)
40+
* [Shutdown Behavior](docs/shutdown_behavior.md)
41+
* [Release Management](docs/release_management.md)
42+
* [Troubleshooting](docs/troubleshooting.md)

container/root/etc/cont-init.d/10-nginx-config.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,9 @@ then
8383
# Add SSL to listen directive
8484
sed -i "s/^[ ]*listen ${CONTAINER_PORT}/ listen ${CONTAINER_PORT} ssl/" $CONF_NGINX_SITE
8585
fi
86+
87+
if [[ $SERVER_ENABLE_NGX_HTTP_JS ]];
88+
then
89+
echo "[nginx] enabling nginx njs module"
90+
sed -i "s/#load_module/load_module/" $CONF_NGINX_SERVER
91+
fi

container/root/etc/nginx/nginx.conf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ error_log /dev/stdout warn;
1919
# Number of file descriptors used for nginx
2020
worker_rlimit_nofile 40000;
2121

22+
# Set SERVER_ENABLE_NGX_HTTP_JS=true to enable this module
23+
#load_module /usr/lib/nginx/modules/ngx_http_js_module.so;
24+
2225

2326
events {
2427
# Optimized to serve many clients with each thread, essential for linux

container/root/scripts/cleanup.sh

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/bin/bash
2+
3+
###############################################################################
4+
# Remove any uneeded packages that we install that is not during runtime
5+
###############################################################################
6+
7+
# Running python will generate .pyc files and it will prevent the folder
8+
# from being deleted. Sample warning:
9+
#
10+
# dpkg: warning: while removing python3.10,
11+
# directory '/usr/lib/python3/dist-packages' not empty so not removed
12+
[[ -d /usr/lib/python3/dist-packages ]] && rm -rf /usr/lib/python3/dist-packages
13+
14+
# Remove unused packages that should not be in the final image
15+
apt-get remove --purge -yq \
16+
curl \
17+
gnupg2 \
18+
lsb-release \
19+
manpages \
20+
manpages-dev \
21+
man-db \
22+
patch \
23+
make \
24+
unattended-upgrades \
25+
python*

0 commit comments

Comments
 (0)