├── .dockerignore
├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── .hadolint.yaml
├── README.md
├── app
└── index.php
├── bins
└── xdebug-mode
├── conf
├── nginx
│ ├── conf.d
│ │ ├── compression.conf
│ │ └── vhost.conf
│ └── nginx.conf
└── supervisord.conf
├── docker-compose.yml
├── entrypoint
├── entrypoint.sh
└── scripts
│ ├── apply_environments.sh
│ ├── config_replace.sh
│ └── docker_install.sh
├── generator
├── Cargo.lock
├── Cargo.toml
└── src
│ ├── dockerfiles.rs
│ ├── generate.rs
│ ├── main.rs
│ ├── structs.rs
│ └── template_parser.rs
├── php-dev-8.dockerfile
├── php
├── opcache-jit.ini
├── pcov.ini
├── profiler.php
├── xdebug.ini
└── xhprof.ini
├── settings.toml
├── templates
├── dependencies.alpine.dockerfile
├── dependencies.debian.dockerfile
├── docker.partial.dockerfile
├── nginx.partial.dockerfile
└── template.dockerfile
└── user
├── .vimrc
└── bashconfig.sh
/.dockerignore:
--------------------------------------------------------------------------------
1 | .git/
2 | .idea/
3 | php-dev-8.dockerfile
4 | docker-compose.yml
5 | app/
6 | templates/
7 | generator/
8 | src/
9 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on: [push, pull_request]
3 |
4 | jobs:
5 | compile:
6 | runs-on: ubuntu-20.04
7 | steps:
8 | - name: checkout
9 | uses: actions/checkout@v1
10 | - uses: actions-rs/toolchain@v1
11 | with:
12 | toolchain: stable
13 | - uses: actions/cache@v2
14 | with:
15 | path: |
16 | ~/.cargo/registry
17 | ~/.cargo/git
18 | generator/target
19 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
20 | - run: |
21 | # enter generator directory
22 | cd generator
23 | # build rust application
24 | cargo build --release
25 | - name: upload artifact
26 | uses: actions/upload-artifact@master
27 | with:
28 | name: generator
29 | path: generator/target/release/generator
30 | retention-days: 1
31 | generate:
32 | name: Generate and lint Dockerfiles
33 | runs-on: ubuntu-20.04
34 | needs: [compile]
35 | strategy:
36 | matrix:
37 | cli: [ dev, prod ]
38 | type: [ alpine, debian, cli ]
39 | steps:
40 | - name: checkout
41 | uses: actions/checkout@v1
42 | - uses: actions/download-artifact@master
43 | with:
44 | name: generator
45 | path: generator
46 | - name: generate dockerfiles
47 | run: |
48 | chmod +x generator/generator
49 | generator/generator ${{ matrix.cli }} --type=${{ matrix.type }}
50 | - name: lint dockerfiles
51 | uses: brpaz/hadolint-action@master
52 | with:
53 | dockerfile: "Dockerfile"
54 | - name: upload artifact
55 | uses: actions/upload-artifact@master
56 | with:
57 | name: Dockerfile-${{ matrix.cli }}-${{ matrix.type }}
58 | path: Dockerfile
59 | retention-days: 1
60 | build-bc:
61 | runs-on: ubuntu-20.04
62 | needs: [ generate ]
63 | if: github.ref == 'refs/heads/main'
64 | steps:
65 | - name: checkout
66 | uses: actions/checkout@v2
67 | - uses: actions/download-artifact@master
68 | with:
69 | name: Dockerfile-dev-alpine
70 | path: .
71 | - name: update php-dev-8.dockerfile
72 | run: cp Dockerfile php-dev-8.dockerfile
73 | - uses: stefanzweifel/git-auto-commit-action@v4
74 | with:
75 | commit_message: "GitHub-Action: Update php 8.0 alpine dockerfile"
76 | - name: Build image
77 | # if: steps.auto-commit-action.outputs.changes_detected == 'true'
78 | run: docker build . --file php-dev-8.dockerfile --tag php8-nginx-xdebug
79 | - name: Log into registry
80 | # if: steps.auto-commit-action.outputs.changes_detected == 'true'
81 | run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login docker.pkg.github.com -u ${{ github.actor }} --password-stdin
82 | - name: Push image
83 | # if: steps.auto-commit-action.outputs.changes_detected == 'true'
84 | run: |
85 | IMAGE_NAME=php8-nginx-xdebug
86 | IMAGE_ID=docker.pkg.github.com/${{ github.repository }}/$IMAGE_NAME
87 | IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
88 | docker tag $IMAGE_NAME $IMAGE_ID:latest
89 | docker push $IMAGE_ID:latest
90 | build-docker:
91 | runs-on: ubuntu-20.04
92 | needs: [ generate ]
93 | if: github.ref == 'refs/heads/main'
94 | strategy:
95 | matrix:
96 | cli: [ dev, prod ]
97 | type: [ alpine, debian, cli ]
98 | steps:
99 | - name: checkout
100 | uses: actions/checkout@v2
101 | - uses: actions/download-artifact@master
102 | with:
103 | name: Dockerfile-${{ matrix.cli }}-${{ matrix.type }}
104 | path: .
105 | - name: Build and Push Dockerfile ${{ matrix.cli }} ${{ matrix.type }}
106 | uses: docker/build-push-action@v1.1.0
107 | env:
108 | DEV_ENV: ${{ fromJSON('["", "-dev"]')[matrix.cli == 'dev'] }}
109 | VARIANT_ENV: ${{ fromJSON('["-nginx", ""]')[matrix.type == 'cli'] }}
110 | with:
111 | username: ${{ secrets.DOCKER_USERNAME }}
112 | password: ${{ secrets.DOCKER_PASSWORD }}
113 | repository: chrisb9/php8
114 | tags: ${{ matrix.type }}${{ env.VARIANT_ENV }}${{ env.DEV_ENV }}
115 | path: .
116 | - name: push README to Dockerhub
117 | uses: christian-korneck/update-container-description-action@v1
118 | env:
119 | DOCKER_USER: ${{ secrets.DOCKER_USERNAME }}
120 | DOCKER_PASS: ${{ secrets.DOCKER_PASSWORD }}
121 | with:
122 | destination_container_repo: chrisb9/php8
123 | provider: dockerhub
124 | readme_file: 'README.md'
125 | sync-readme:
126 | runs-on: ubuntu-20.04
127 | if: github.ref == 'refs/heads/main'
128 | steps:
129 | - name: checkout
130 | uses: actions/checkout@v2
131 | - name: push README to Dockerhub
132 | uses: christian-korneck/update-container-description-action@v1
133 | env:
134 | DOCKER_USER: ${{ secrets.DOCKER_USERNAME }}
135 | DOCKER_PASS: ${{ secrets.DOCKER_PASSWORD }}
136 | with:
137 | destination_container_repo: chrisb9/php8
138 | provider: dockerhub
139 | readme_file: 'README.md'
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | *.log
3 | *.pid
4 | generator/target
5 | Dockerfile
--------------------------------------------------------------------------------
/.hadolint.yaml:
--------------------------------------------------------------------------------
1 | ignored:
2 | - DL3008
3 | - DL3003
4 | - DL4006
5 | - SC2086
6 | - DL3002
7 | - DL3018
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # PHP 8.0 for development and production
4 |
5 | > **Note**:
6 | > This image is transitioning from a simple dev image to a more configurable and extensible image
7 | > Therefore it is currently being pushed into two different docker repositories:
8 | > (old:) [https://hub.docker.com/r/chrisb9/php8-nginx-xdebug](https://hub.docker.com/r/chrisb9/php8-nginx-xdebug)
9 | > (new:) [https://hub.docker.com/r/chrisb9/php8](https://hub.docker.com/r/chrisb9/php8)
10 |
11 | ## The Images:
12 |
13 | There are three image configurations in two different types:
14 |
15 | | Image Type | Image Variant | With nginx |
16 | |:----------:|:-------------:|:----------:|
17 | | Alpine | dev and prod | yes |
18 | | Debian | dev and prod | yes |
19 | | CLI | dev and prod | no |
20 |
21 | ### current features
22 |
23 | - **nginx based image:** nginx with brotli and http2 enabled
24 | - **dev image:** php 8.0 ✨ (with xdebug, opcache, ffi, and jit enabled by default)
25 | - **prod image:** php 8.0 ✨ (with opcache, and jit enabled by default)
26 | - **dev image:** xdebug 3.0 (set to profile, debug and develop-mode)
27 | - **dev image:** pcov
28 | - composer v2.0 (composer 1.0 has been removed)
29 | - bash (with auto-completion extension and colored)
30 | - webp and image-optimizers
31 | - mariadb support
32 | - **cli image**: no fpm and no nginx preinstalled - this is your smaller variant, not based on alpine (yet)
33 |
34 | planned:
35 | - mongodb support
36 | - apache-based image
37 | - easier extension installation
38 | - tideways profiler with perf-tools enabled
39 |
40 | This repository does only provide Dockerfiles for php 8.0 and upwards.
41 | If there is enough traction, I might add PHP 7.4 too (or feel free to add it)
42 |
43 | ### docker-socket
44 |
45 | If docker socket has been mounted as a volume into the container,
46 | then each startup checks the availability of the docker command and if not available installs it.
47 | > Note: This is currently only available in alpine images: WIP
48 |
49 | ## xdebug settings:
50 |
51 | Some xdebug settings have been preconfigured, such as:
52 | - `xdebug.mode=profile,develop,coverage`
53 | - `xdebug.client_port=9003`
54 | - `xdebug.discover_client_host=1`
55 | - `xdebug.idekey=PHPSTORM`
56 |
57 | Through the environment-variable `XDEBUG_HOST` the client_host can be changed on login
58 |
59 | ### xdebug tools:
60 | - `xdebug-enable` enabled xdebug and restarts php
61 | - `xdebug-disable` disables xdebug and restarts php
62 |
63 | ## testing this dockerfile:
64 |
65 | just run `git clone && docker-compose up -d`
66 | then open up your browser and go to this container.
67 |
68 | in the app-folder are two files index.php and Test.php.
69 | They are meant as a playground to test the newest features of php 8.0
70 |
71 | ## Contributing
72 |
73 | todo...
74 |
--------------------------------------------------------------------------------
/app/index.php:
--------------------------------------------------------------------------------
1 | > /tmp/xdebug.ini
13 | $SUDO mv /tmp/xdebug.ini /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
14 | test ! -z "$IS_CLI" && $SUDO supervisorctl -c /opt/docker/supervisord.conf restart php-fpm:php-fpm
15 |
--------------------------------------------------------------------------------
/conf/nginx/conf.d/compression.conf:
--------------------------------------------------------------------------------
1 | gzip on;
2 | gzip_vary on;
3 | gzip_proxied any;
4 | gzip_comp_level 6;
5 | gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss application/atom+xml image/svg+xml;
6 |
7 | brotli on;
8 | brotli_comp_level 6;
9 | brotli_static on;
10 | brotli_types application/atom+xml application/javascript application/json application/rss+xml
11 | application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype
12 | application/x-font-ttf application/x-javascript application/xhtml+xml application/xml
13 | font/eot font/opentype font/otf font/truetype image/svg+xml image/vnd.microsoft.icon
14 | image/x-icon image/x-win-bitmap text/css text/javascript text/plain text/xml;
--------------------------------------------------------------------------------
/conf/nginx/conf.d/vhost.conf:
--------------------------------------------------------------------------------
1 | server {
2 | listen 80;
3 | server_name ${WEB_ALIAS_DOMAIN};
4 |
5 | root ${WEB_DOCUMENT_ROOT};
6 | index ${WEB_DOCUMENT_INDEX};
7 |
8 | client_max_body_size ${NGINX_CLIENT_MAX_BODY};
9 |
10 | location / {
11 | try_files $uri $uri/ /${WEB_DOCUMENT_INDEX}?$query_string;
12 | }
13 |
14 | location ~ \.php {
15 | fastcgi_index index.php;
16 | fastcgi_pass localhost:9000;
17 |
18 | include /etc/nginx/fastcgi_params;
19 | fastcgi_split_path_info ^(.+\.php)(/.+)$;
20 | fastcgi_param PATH_INFO $fastcgi_path_info;
21 | fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
22 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
23 | fastcgi_read_timeout ${WEB_PHP_TIMEOUT};
24 | }
25 |
26 |
27 | location ~* ${WEB_NO_CACHE_PATTERN} {
28 | expires off;
29 | add_header Cache-Control private;
30 |
31 | try_files $uri $uri/ /${WEB_DOCUMENT_INDEX}?$query_string;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/conf/nginx/nginx.conf:
--------------------------------------------------------------------------------
1 | user nginx;
2 | worker_processes 1;
3 |
4 | include /etc/nginx/modules-enabled/*.conf;
5 |
6 | error_log /var/log/nginx/error.log warn;
7 | pid /var/run/nginx.pid;
8 |
9 | events {
10 | worker_connections 1024;
11 | }
12 |
13 | http {
14 | include /etc/nginx/mime.types;
15 | default_type application/octet-stream;
16 |
17 | log_format main '$remote_addr - $remote_user [$time_local] "$request" '
18 | '$status $body_bytes_sent "$http_referer" '
19 | '"$http_user_agent" "$http_x_forwarded_for"';
20 |
21 | access_log /var/log/nginx/access.log main;
22 |
23 | sendfile on;
24 | #tcp_nopush on;
25 |
26 | keepalive_timeout 65;
27 |
28 | include /opt/docker/nginx/conf.d/*.conf;
29 | }
30 |
--------------------------------------------------------------------------------
/conf/supervisord.conf:
--------------------------------------------------------------------------------
1 | [supervisord]
2 | logfile=/var/log/supervisord/supervisord.log
3 | childlogdir=/var/log/supervisord/
4 | user=root
5 | pidfile=/run/supervisord.pid
6 | logfile_maxbytes=50MB
7 | logfile_backups=10
8 | loglevel=info
9 | nodaemon=true
10 |
11 | [unix_http_server]
12 | file=/run/supervisord.sock ; the path to the socket file
13 |
14 | [supervisorctl]
15 | serverurl=unix:///run/supervisord.sock
16 |
17 | [rpcinterface:supervisor]
18 | supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
19 |
20 | [program:php-fpm]
21 | command=php-fpm --nodaemonize
22 | startsecs = 0
23 | autostart = true
24 | autorestart = true
25 | stdout_logfile=/dev/stdout
26 | stdout_logfile_maxbytes=0
27 | stderr_logfile=/dev/stderr
28 | stderr_logfile_maxbytes=0
29 |
30 | [program:nginx]
31 | command=nginx -c /opt/docker/nginx/nginx.conf -g "daemon off;"
32 | startsecs = 0
33 | autostart = true
34 | autorestart = true
35 | stdout_logfile=/dev/stdout
36 | stdout_logfile_maxbytes=0
37 | stderr_logfile=/dev/stderr
38 | stderr_logfile_maxbytes=0
39 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.5'
2 |
3 | services:
4 | php:
5 | build:
6 | dockerfile: Dockerfile
7 | context: .
8 | volumes:
9 | - ./app:/app
10 | environment:
11 | - VIRTUAL_HOST=php8.local.cben.dev
12 | - php.memory_limit=-1
13 |
14 | lint:
15 | image: hadolint/hadolint
16 | volumes:
17 | - ./.hadolint.yaml:/root/.config/.hadolint.yaml:ro
18 | - ./Dockerfile:/Dockerfile:ro
19 | command: "hadolint /Dockerfile"
20 |
21 | networks:
22 | default:
23 | external:
24 | name: global
25 |
--------------------------------------------------------------------------------
/entrypoint/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o pipefail
4 | set -o errtrace
5 |
6 | for filename in /entrypoint.d/*.sh; do
7 | [ -e "$filename" ] || continue;
8 | echo "Running now: $filename"
9 | bash "$filename"
10 | done;
11 |
12 | exec /usr/bin/supervisord -nc /opt/docker/supervisord.conf
13 |
--------------------------------------------------------------------------------
/entrypoint/scripts/apply_environments.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | function listEnvs() {
4 | env | grep "^${1}" | cut -d= -f1
5 | }
6 |
7 | function getEnvVar() {
8 | awk "BEGIN {print ENVIRON[\"$1\"]}"
9 | }
10 |
11 | for ENV_VAR in $(listEnvs "php\."); do
12 | env_key=${ENV_VAR#php.}
13 | env_val=$(getEnvVar "$ENV_VAR")
14 |
15 | echo "$env_key = ${env_val}" >> /usr/local/etc/php/conf.d/x.override.php.ini
16 | done
17 |
18 | if [[ -n "${XDEBUG_HOST}" ]]; then
19 | cat /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini | sed "s|\#\ xdebug\.client\_host\ \=|xdebug\.client\_host=${XDEBUG_HOST}|g" >> /tmp/xdebug.ini
20 | mv /tmp/xdebug.ini /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
21 | fi
22 |
23 | test -z "$PHP_MEMORY_LIMIT" && echo "memory_limit = ${PHP_MEMORY_LIMIT}" >> /usr/local/etc/php/conf.d/x.override.php.ini
24 | test -z "$PHP_DISPLAY_ERRORS" && echo "memory_limit = ${PHP_DISPLAY_ERRORS}" >> /usr/local/etc/php/conf.d/x.override.php.ini
--------------------------------------------------------------------------------
/entrypoint/scripts/config_replace.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ambr --no-interactive '${WEB_DOCUMENT_ROOT}' "$WEB_DOCUMENT_ROOT" /opt/docker/nginx/
4 | ambr --no-interactive '${WEB_DOCUMENT_INDEX}' "$WEB_DOCUMENT_INDEX" /opt/docker/nginx/
5 | ambr --no-interactive '${WEB_ALIAS_DOMAIN}' "$WEB_ALIAS_DOMAIN" /opt/docker/nginx/
6 | ambr --no-interactive '${WEB_PHP_TIMEOUT}' "$WEB_PHP_TIMEOUT" /opt/docker/nginx/
7 | ambr --no-interactive '${WEB_PHP_SOCKET}' "$WEB_PHP_SOCKET" /opt/docker/nginx/
8 | ambr --no-interactive '${NGINX_CLIENT_MAX_BODY}' "$NGINX_CLIENT_MAX_BODY" /opt/docker/nginx/
9 | ambr --no-interactive '${WEB_NO_CACHE_PATTERN}' "$WEB_NO_CACHE_PATTERN" /opt/docker/nginx/
--------------------------------------------------------------------------------
/entrypoint/scripts/docker_install.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | if [ -e /var/run/docker.sock ] && [ -n "$IS_ALPINE" ]; then
4 | apk add docker
5 | fi
6 | if [ -e /var/run/docker.sock ] && [ -z "$IS_ALPINE" ]; then
7 | apt update && apt install docker
8 | fi
9 |
--------------------------------------------------------------------------------
/generator/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | [[package]]
4 | name = "addr2line"
5 | version = "0.14.0"
6 | source = "registry+https://github.com/rust-lang/crates.io-index"
7 | checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423"
8 | dependencies = [
9 | "gimli",
10 | ]
11 |
12 | [[package]]
13 | name = "adler"
14 | version = "0.2.3"
15 | source = "registry+https://github.com/rust-lang/crates.io-index"
16 | checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
17 |
18 | [[package]]
19 | name = "aho-corasick"
20 | version = "0.7.15"
21 | source = "registry+https://github.com/rust-lang/crates.io-index"
22 | checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
23 | dependencies = [
24 | "memchr",
25 | ]
26 |
27 | [[package]]
28 | name = "arrayvec"
29 | version = "0.5.2"
30 | source = "registry+https://github.com/rust-lang/crates.io-index"
31 | checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
32 |
33 | [[package]]
34 | name = "autocfg"
35 | version = "1.0.1"
36 | source = "registry+https://github.com/rust-lang/crates.io-index"
37 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
38 |
39 | [[package]]
40 | name = "backtrace"
41 | version = "0.3.54"
42 | source = "registry+https://github.com/rust-lang/crates.io-index"
43 | checksum = "2baad346b2d4e94a24347adeee9c7a93f412ee94b9cc26e5b59dea23848e9f28"
44 | dependencies = [
45 | "addr2line",
46 | "cfg-if 1.0.0",
47 | "libc",
48 | "miniz_oxide",
49 | "object",
50 | "rustc-demangle",
51 | ]
52 |
53 | [[package]]
54 | name = "bitflags"
55 | version = "1.2.1"
56 | source = "registry+https://github.com/rust-lang/crates.io-index"
57 | checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
58 |
59 | [[package]]
60 | name = "cfg-if"
61 | version = "0.1.10"
62 | source = "registry+https://github.com/rust-lang/crates.io-index"
63 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
64 |
65 | [[package]]
66 | name = "cfg-if"
67 | version = "1.0.0"
68 | source = "registry+https://github.com/rust-lang/crates.io-index"
69 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
70 |
71 | [[package]]
72 | name = "config"
73 | version = "0.10.1"
74 | source = "registry+https://github.com/rust-lang/crates.io-index"
75 | checksum = "19b076e143e1d9538dde65da30f8481c2a6c44040edb8e02b9bf1351edb92ce3"
76 | dependencies = [
77 | "lazy_static",
78 | "nom",
79 | "rust-ini",
80 | "serde 1.0.117",
81 | "serde-hjson",
82 | "serde_json",
83 | "toml",
84 | "yaml-rust",
85 | ]
86 |
87 | [[package]]
88 | name = "failure"
89 | version = "0.1.8"
90 | source = "registry+https://github.com/rust-lang/crates.io-index"
91 | checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
92 | dependencies = [
93 | "backtrace",
94 | "failure_derive",
95 | ]
96 |
97 | [[package]]
98 | name = "failure_derive"
99 | version = "0.1.8"
100 | source = "registry+https://github.com/rust-lang/crates.io-index"
101 | checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
102 | dependencies = [
103 | "proc-macro2",
104 | "quote",
105 | "syn",
106 | "synstructure",
107 | ]
108 |
109 | [[package]]
110 | name = "generator"
111 | version = "0.1.0"
112 | dependencies = [
113 | "config",
114 | "failure",
115 | "failure_derive",
116 | "seahorse",
117 | "serde 1.0.117",
118 | "serde_derive",
119 | "terminal_color_builder",
120 | "tinytemplate",
121 | ]
122 |
123 | [[package]]
124 | name = "gimli"
125 | version = "0.23.0"
126 | source = "registry+https://github.com/rust-lang/crates.io-index"
127 | checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
128 |
129 | [[package]]
130 | name = "itoa"
131 | version = "0.4.6"
132 | source = "registry+https://github.com/rust-lang/crates.io-index"
133 | checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
134 |
135 | [[package]]
136 | name = "lazy_static"
137 | version = "1.4.0"
138 | source = "registry+https://github.com/rust-lang/crates.io-index"
139 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
140 |
141 | [[package]]
142 | name = "lexical-core"
143 | version = "0.7.4"
144 | source = "registry+https://github.com/rust-lang/crates.io-index"
145 | checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616"
146 | dependencies = [
147 | "arrayvec",
148 | "bitflags",
149 | "cfg-if 0.1.10",
150 | "ryu",
151 | "static_assertions",
152 | ]
153 |
154 | [[package]]
155 | name = "libc"
156 | version = "0.2.80"
157 | source = "registry+https://github.com/rust-lang/crates.io-index"
158 | checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
159 |
160 | [[package]]
161 | name = "linked-hash-map"
162 | version = "0.3.0"
163 | source = "registry+https://github.com/rust-lang/crates.io-index"
164 | checksum = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd"
165 | dependencies = [
166 | "serde 0.8.23",
167 | "serde_test",
168 | ]
169 |
170 | [[package]]
171 | name = "linked-hash-map"
172 | version = "0.5.3"
173 | source = "registry+https://github.com/rust-lang/crates.io-index"
174 | checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
175 |
176 | [[package]]
177 | name = "memchr"
178 | version = "2.3.4"
179 | source = "registry+https://github.com/rust-lang/crates.io-index"
180 | checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
181 |
182 | [[package]]
183 | name = "miniz_oxide"
184 | version = "0.4.3"
185 | source = "registry+https://github.com/rust-lang/crates.io-index"
186 | checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
187 | dependencies = [
188 | "adler",
189 | "autocfg",
190 | ]
191 |
192 | [[package]]
193 | name = "nom"
194 | version = "5.1.2"
195 | source = "registry+https://github.com/rust-lang/crates.io-index"
196 | checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
197 | dependencies = [
198 | "lexical-core",
199 | "memchr",
200 | "version_check",
201 | ]
202 |
203 | [[package]]
204 | name = "num-traits"
205 | version = "0.1.43"
206 | source = "registry+https://github.com/rust-lang/crates.io-index"
207 | checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
208 | dependencies = [
209 | "num-traits 0.2.14",
210 | ]
211 |
212 | [[package]]
213 | name = "num-traits"
214 | version = "0.2.14"
215 | source = "registry+https://github.com/rust-lang/crates.io-index"
216 | checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
217 | dependencies = [
218 | "autocfg",
219 | ]
220 |
221 | [[package]]
222 | name = "object"
223 | version = "0.22.0"
224 | source = "registry+https://github.com/rust-lang/crates.io-index"
225 | checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"
226 |
227 | [[package]]
228 | name = "proc-macro2"
229 | version = "1.0.24"
230 | source = "registry+https://github.com/rust-lang/crates.io-index"
231 | checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
232 | dependencies = [
233 | "unicode-xid",
234 | ]
235 |
236 | [[package]]
237 | name = "quote"
238 | version = "1.0.7"
239 | source = "registry+https://github.com/rust-lang/crates.io-index"
240 | checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
241 | dependencies = [
242 | "proc-macro2",
243 | ]
244 |
245 | [[package]]
246 | name = "regex"
247 | version = "1.4.2"
248 | source = "registry+https://github.com/rust-lang/crates.io-index"
249 | checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c"
250 | dependencies = [
251 | "aho-corasick",
252 | "memchr",
253 | "regex-syntax",
254 | "thread_local",
255 | ]
256 |
257 | [[package]]
258 | name = "regex-syntax"
259 | version = "0.6.21"
260 | source = "registry+https://github.com/rust-lang/crates.io-index"
261 | checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
262 |
263 | [[package]]
264 | name = "rust-ini"
265 | version = "0.13.0"
266 | source = "registry+https://github.com/rust-lang/crates.io-index"
267 | checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2"
268 |
269 | [[package]]
270 | name = "rustc-demangle"
271 | version = "0.1.18"
272 | source = "registry+https://github.com/rust-lang/crates.io-index"
273 | checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232"
274 |
275 | [[package]]
276 | name = "ryu"
277 | version = "1.0.5"
278 | source = "registry+https://github.com/rust-lang/crates.io-index"
279 | checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
280 |
281 | [[package]]
282 | name = "seahorse"
283 | version = "1.1.1"
284 | source = "registry+https://github.com/rust-lang/crates.io-index"
285 | checksum = "ce7d9440e2865cce0db733bdc530591b37d37a2d32badace34a1fc9ba5686d58"
286 |
287 | [[package]]
288 | name = "serde"
289 | version = "0.8.23"
290 | source = "registry+https://github.com/rust-lang/crates.io-index"
291 | checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8"
292 |
293 | [[package]]
294 | name = "serde"
295 | version = "1.0.117"
296 | source = "registry+https://github.com/rust-lang/crates.io-index"
297 | checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a"
298 |
299 | [[package]]
300 | name = "serde-hjson"
301 | version = "0.9.1"
302 | source = "registry+https://github.com/rust-lang/crates.io-index"
303 | checksum = "6a3a4e0ea8a88553209f6cc6cfe8724ecad22e1acf372793c27d995290fe74f8"
304 | dependencies = [
305 | "lazy_static",
306 | "linked-hash-map 0.3.0",
307 | "num-traits 0.1.43",
308 | "regex",
309 | "serde 0.8.23",
310 | ]
311 |
312 | [[package]]
313 | name = "serde_derive"
314 | version = "1.0.117"
315 | source = "registry+https://github.com/rust-lang/crates.io-index"
316 | checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e"
317 | dependencies = [
318 | "proc-macro2",
319 | "quote",
320 | "syn",
321 | ]
322 |
323 | [[package]]
324 | name = "serde_json"
325 | version = "1.0.59"
326 | source = "registry+https://github.com/rust-lang/crates.io-index"
327 | checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95"
328 | dependencies = [
329 | "itoa",
330 | "ryu",
331 | "serde 1.0.117",
332 | ]
333 |
334 | [[package]]
335 | name = "serde_test"
336 | version = "0.8.23"
337 | source = "registry+https://github.com/rust-lang/crates.io-index"
338 | checksum = "110b3dbdf8607ec493c22d5d947753282f3bae73c0f56d322af1e8c78e4c23d5"
339 | dependencies = [
340 | "serde 0.8.23",
341 | ]
342 |
343 | [[package]]
344 | name = "static_assertions"
345 | version = "1.1.0"
346 | source = "registry+https://github.com/rust-lang/crates.io-index"
347 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
348 |
349 | [[package]]
350 | name = "syn"
351 | version = "1.0.48"
352 | source = "registry+https://github.com/rust-lang/crates.io-index"
353 | checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac"
354 | dependencies = [
355 | "proc-macro2",
356 | "quote",
357 | "unicode-xid",
358 | ]
359 |
360 | [[package]]
361 | name = "synstructure"
362 | version = "0.12.4"
363 | source = "registry+https://github.com/rust-lang/crates.io-index"
364 | checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
365 | dependencies = [
366 | "proc-macro2",
367 | "quote",
368 | "syn",
369 | "unicode-xid",
370 | ]
371 |
372 | [[package]]
373 | name = "terminal_color_builder"
374 | version = "0.1.1"
375 | source = "registry+https://github.com/rust-lang/crates.io-index"
376 | checksum = "51bc10d4f2e7a2580c9fbeb550ef748c81430cfaffb046f047204bb5a75dbff0"
377 |
378 | [[package]]
379 | name = "thread_local"
380 | version = "1.0.1"
381 | source = "registry+https://github.com/rust-lang/crates.io-index"
382 | checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
383 | dependencies = [
384 | "lazy_static",
385 | ]
386 |
387 | [[package]]
388 | name = "tinytemplate"
389 | version = "1.1.0"
390 | source = "registry+https://github.com/rust-lang/crates.io-index"
391 | checksum = "6d3dc76004a03cec1c5932bca4cdc2e39aaa798e3f82363dd94f9adf6098c12f"
392 | dependencies = [
393 | "serde 1.0.117",
394 | "serde_json",
395 | ]
396 |
397 | [[package]]
398 | name = "toml"
399 | version = "0.5.7"
400 | source = "registry+https://github.com/rust-lang/crates.io-index"
401 | checksum = "75cf45bb0bef80604d001caaec0d09da99611b3c0fd39d3080468875cdb65645"
402 | dependencies = [
403 | "serde 1.0.117",
404 | ]
405 |
406 | [[package]]
407 | name = "unicode-xid"
408 | version = "0.2.1"
409 | source = "registry+https://github.com/rust-lang/crates.io-index"
410 | checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
411 |
412 | [[package]]
413 | name = "version_check"
414 | version = "0.9.2"
415 | source = "registry+https://github.com/rust-lang/crates.io-index"
416 | checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
417 |
418 | [[package]]
419 | name = "yaml-rust"
420 | version = "0.4.4"
421 | source = "registry+https://github.com/rust-lang/crates.io-index"
422 | checksum = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d"
423 | dependencies = [
424 | "linked-hash-map 0.5.3",
425 | ]
426 |
--------------------------------------------------------------------------------
/generator/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "generator"
3 | version = "0.1.0"
4 | authors = ["Christian Rodriguez Benthake "]
5 | homepage = "https://cben.dev"
6 | repository = "https://github.com/ChrisB9/php8-xdebug"
7 | license = "MIT"
8 | edition = "2018"
9 |
10 | [dependencies]
11 | tinytemplate = "1.0"
12 | serde = "^1.0"
13 | serde_derive = "^1.0"
14 | failure = "0.1.8"
15 | failure_derive = "0.1.8"
16 | seahorse = "1.1"
17 | terminal_color_builder = "0.1.1"
18 | config = "^0.10"
--------------------------------------------------------------------------------
/generator/src/dockerfiles.rs:
--------------------------------------------------------------------------------
1 | use crate::generate::Generate;
2 | use crate::structs::*;
3 | use std::collections::HashMap;
4 |
5 | fn get_from(container_type: &ContainerType) -> String {
6 | String::from(match container_type {
7 | ContainerType::ALPINE => "php:8.0.0-fpm-alpine",
8 | ContainerType::DEBIAN => "php:8.0.0-fpm",
9 | ContainerType::CLI => "php:8.0.0-cli",
10 | })
11 | }
12 |
13 | fn get_is_alpine(container_type: &ContainerType) -> bool {
14 | *container_type == ContainerType::ALPINE
15 | }
16 |
17 | fn get_is_web(container_type: &ContainerType) -> bool {
18 | *container_type != ContainerType::CLI
19 | }
20 |
21 | impl Generate for ProdDockerfile {
22 | fn new(container_type: Option) -> ProdDockerfile {
23 | let container_type: ContainerType = container_type.unwrap_or(ContainerType::ALPINE);
24 | let from: String = get_from(&container_type);
25 | let use_apk: bool = get_is_alpine(&container_type);
26 | let is_web: bool = get_is_web(&container_type);
27 | ProdDockerfile {
28 | base: Dockerfile {
29 | from,
30 | container_type,
31 | envs: HashMap::new(),
32 | use_apk,
33 | is_web,
34 | },
35 | is_dev: false,
36 | }
37 | }
38 | }
39 |
40 | impl Generate for DevDockerfile {
41 | fn new(container_type: Option) -> DevDockerfile {
42 | let container_type: ContainerType = container_type.unwrap_or(ContainerType::ALPINE);
43 | let mut envs: HashMap = HashMap::new();
44 | envs.insert(String::from("XDEBUG_VERSION"), String::from("3.0.0"));
45 | let from: String = get_from(&container_type);
46 | let use_apk: bool = get_is_alpine(&container_type);
47 | let is_web: bool = get_is_web(&container_type);
48 | DevDockerfile {
49 | base: Dockerfile {
50 | from,
51 | container_type,
52 | envs,
53 | use_apk,
54 | is_web,
55 | },
56 | is_dev: true,
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/generator/src/generate.rs:
--------------------------------------------------------------------------------
1 | use std::path::Path;
2 | use std::fs;
3 | use crate::template_parser::Parsing;
4 | use serde::Serialize;
5 | use std::fs::File;
6 | use std::io::prelude::*;
7 | use crate::structs::ContainerType;
8 | use config::Config;
9 | use std::collections::HashMap;
10 | use serde::export::fmt::Debug;
11 |
12 | pub trait Generate: Serialize + Debug {
13 | fn new(container_type: Option) -> Self;
14 |
15 | fn load_config(&self) -> HashMap {
16 | let mut settings: Config = Config::default();
17 | settings.merge(config::File::with_name("settings")).unwrap();
18 | settings.try_into::>().unwrap()
19 | }
20 |
21 | fn generate(&self) -> Result> {
22 | let config = self.load_config();
23 | let parser = Parsing::new(config);
24 | match parser.render(&self) {
25 | Err(e) => Err(e),
26 | Ok(r) => Ok(r),
27 | }
28 | }
29 |
30 | fn to_file(&self) -> Result<(), failure::Error> {
31 | let config = self.load_config();
32 | let filename: &str = &config["output_path"];
33 | if Path::new(filename).exists() {
34 | fs::remove_file(filename)?;
35 | }
36 | let mut file = File::create(filename)?;
37 | let result = self.generate()?;
38 | file.write_all(result.as_bytes())?;
39 | Ok(())
40 | }
41 | }
--------------------------------------------------------------------------------
/generator/src/main.rs:
--------------------------------------------------------------------------------
1 | #[macro_use]
2 | pub extern crate serde_derive;
3 | pub extern crate tinytemplate;
4 | pub extern crate failure_derive;
5 |
6 | mod dockerfiles;
7 | mod structs;
8 | mod template_parser;
9 | mod generate;
10 |
11 | use structs::*;
12 | use generate::Generate;
13 | use seahorse::{App, Context, Command, Flag, FlagType};
14 | use std::env;
15 | use std::fmt::Display;
16 | use terminal_color_builder::OutputFormatter as tcb;
17 | use seahorse::error::FlagError;
18 |
19 | pub fn main() {
20 | let args: Vec = env::args().collect();
21 | let app = App::new(cmd(env!("CARGO_PKG_NAME")))
22 | .description(cmd("generate php 8.0 dockerfile by template"))
23 | .command(generate_prod())
24 | .command(generate_test());
25 |
26 | app.run(args);
27 | }
28 |
29 | fn success(t: T) -> () {
30 | println!("{}", tcb::new().fg().hex("#fff").bg().green().text(t.to_string()).print());
31 | }
32 |
33 | fn error(t: T) -> String {
34 | format!("{}", tcb::new().fg().hex("#fff").bg().red().text(t.to_string()).print())
35 | }
36 |
37 | fn cmd(str: &str) -> String {
38 | tcb::new().fg().hex("#6f0").text_str(str).print()
39 | }
40 |
41 | fn parse_container_type(c: &Context) -> ContainerType {
42 | match c.string_flag("type") {
43 | Ok(t) => match &*t {
44 | "alpine" => ContainerType::ALPINE,
45 | "debian" => ContainerType::DEBIAN,
46 | "cli" => ContainerType::CLI,
47 | _ => panic!("{} {} {}", error("undefined container-type"), t, ": available types are debian, alpine, cli")
48 | }
49 | Err(e) => match e {
50 | FlagError::NotFound => ContainerType::ALPINE,
51 | _ => panic!("{} {:?}", error("Flag-Error"), e),
52 | }
53 | }
54 | }
55 |
56 | fn generate_prod_action(c: &Context) {
57 | let container_type = parse_container_type(c);
58 | let dockerfile: ProdDockerfile = Generate::new(Option::from(container_type));
59 | match dockerfile.to_file() {
60 | Err(e) => panic!(format!("{:?}", e)),
61 | _ => success("Successfully generated file"),
62 | }
63 | }
64 |
65 | fn generate_test_action(c: &Context) {
66 | let container_type = parse_container_type(c);
67 | let dockerfile: DevDockerfile = Generate::new(Option::from(container_type));
68 | match dockerfile.to_file() {
69 | Err(e) => panic!(format!("{:?}", e)),
70 | _ => success("Successfully generated file"),
71 | }
72 | }
73 |
74 | fn generate_prod() -> Command {
75 | Command::new("prod")
76 | .description(cmd("generate prod-php dockerfile"))
77 | .alias(cmd("p"))
78 | .usage(cmd("cli prod"))
79 | .action(generate_prod_action)
80 | .flag(
81 | Flag::new("type", FlagType::String)
82 | .description(cmd("Build either a debian-based or a alpine-based image (--type=debian or --type=alpine)"))
83 | .alias("t")
84 | )
85 | }
86 |
87 | fn generate_test() -> Command {
88 | Command::new("dev")
89 | .description(cmd("generate dev-php dockerfile"))
90 | .alias(cmd("d"))
91 | .usage(cmd("cli dev"))
92 | .action(generate_test_action)
93 | .flag(
94 | Flag::new("type", FlagType::String)
95 | .description(cmd("Build either a debian-based or a alpine-based image (--type=debian or --type=alpine)"))
96 | .alias("t")
97 | )
98 | }
99 |
--------------------------------------------------------------------------------
/generator/src/structs.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 |
3 | #[derive(PartialOrd, PartialEq, Debug, Serialize)]
4 | pub enum ContainerType {
5 | ALPINE,
6 | DEBIAN,
7 | CLI,
8 | }
9 |
10 | #[derive(Debug, Serialize)]
11 | pub struct Dockerfile {
12 | pub from: String,
13 | pub container_type: ContainerType,
14 | pub envs: HashMap,
15 | pub use_apk: bool,
16 | pub is_web: bool,
17 | }
18 |
19 | #[derive(Debug, Serialize)]
20 | pub struct ProdDockerfile {
21 | pub base: Dockerfile,
22 | pub is_dev: bool,
23 | }
24 |
25 | #[derive(Debug, Serialize)]
26 | pub struct DevDockerfile {
27 | pub base: Dockerfile,
28 | pub is_dev: bool,
29 | }
--------------------------------------------------------------------------------
/generator/src/template_parser.rs:
--------------------------------------------------------------------------------
1 | use tinytemplate::TinyTemplate;
2 | use std::{fs::{File, read_dir}, io::prelude::*, collections::HashMap, path::Path, io};
3 | use failure::Fail;
4 | use serde::Serialize;
5 | use serde::export::fmt::Debug;
6 |
7 | #[derive(Fail, Debug)]
8 | #[fail(display = "An error occurred while parsing the template: {}.", _0)]
9 | pub struct TemplatingError(String);
10 |
11 | pub struct Parsing {
12 | config: HashMap
13 | }
14 |
15 | struct TemplateFileCollection {
16 | template_content: HashMap
17 | }
18 |
19 | impl TemplateFileCollection {
20 | pub fn new() -> TemplateFileCollection {
21 | TemplateFileCollection {
22 | template_content: HashMap::new(),
23 | }
24 | }
25 |
26 | fn read_dirs(dir: &str) -> io::Result> {
27 | let path = Path::new(dir);
28 | let mut collection: Vec = vec![];
29 | if path.is_dir() {
30 | for file in read_dir(path)? {
31 | let file = file?;
32 | if !file.path().is_dir() {
33 | collection.push(file.path().as_os_str().to_str().unwrap().to_string());
34 | }
35 | }
36 | }
37 | Ok(collection)
38 | }
39 |
40 | pub fn read_for_dir(&mut self, dir: &str) -> io::Result<()> {
41 | let collection = TemplateFileCollection::read_dirs(dir)?;
42 | for file in &collection {
43 | self.add_file_content(file)?;
44 | }
45 | Ok(())
46 | }
47 |
48 | pub fn read_file(file: &str) -> io::Result {
49 | let mut handle = File::open(file)?;
50 | let mut contents = String::new();
51 | handle.read_to_string(&mut contents)?;
52 | Ok(contents)
53 | }
54 |
55 | pub fn add_file_content(&mut self, file: &str) -> io::Result<()> {
56 | let contents = TemplateFileCollection::read_file(file).unwrap();
57 | let filename = Path::new(&file).file_name().unwrap();
58 | let mut filename = String::from(filename.to_str().unwrap());
59 | filename = filename.replace(".", "_");
60 | self.template_content.insert(filename, contents);
61 | Ok(())
62 | }
63 | }
64 |
65 | impl Parsing {
66 | pub fn new(config: HashMap) -> Parsing {
67 | Parsing {
68 | config,
69 | }
70 | }
71 |
72 | fn get_error(&self, message: &str) -> Box {
73 | Box::new(TemplatingError(String::from(message)))
74 | }
75 |
76 | pub fn render(&self, context: &S) -> Result> where S: Serialize + Debug {
77 | let mut template = TinyTemplate::new();
78 | let mut collection = TemplateFileCollection::new();
79 | match collection.read_for_dir(&self.config["template_path"]) {
80 | Ok(_r) => (),
81 | Err(_e) => return Err(self.get_error("Failed parsing template directory")),
82 | };
83 | for file in &collection.template_content {
84 | match template.add_template(file.0, file.1) {
85 | Ok(_r) => (),
86 | Err(_e) => return Err(self.get_error(&format!("Failed parsing template directory for dockerfile {:?} {:?}", _e, context))),
87 | };
88 | }
89 |
90 | return match template.render(&self.config["base_template"], &context) {
91 | Err(e) => {
92 | println!("{}", e);
93 | Err(self.get_error("Rendering Template failed"))
94 | },
95 | Ok(r) => Ok(r),
96 | };
97 | }
98 | }
--------------------------------------------------------------------------------
/php-dev-8.dockerfile:
--------------------------------------------------------------------------------
1 | FROM php:8.0.0-fpm-alpine
2 |
3 | ENV TERM="xterm" \
4 | LANG="C.UTF-8" \
5 | LC_ALL="C.UTF-8"
6 | ENV DOCKER_CONF_HOME=/opt/docker/
7 | ENV APPLICATION_USER=application \
8 | APPLICATION_GROUP=application \
9 | APPLICATION_PATH=/app \
10 | APPLICATION_UID=1000 \
11 | APPLICATION_GID=1000
12 | ENV WEB_DOCUMENT_ROOT=/app \
13 | WEB_DOCUMENT_INDEX=index.php \
14 | WEB_ALIAS_DOMAIN=*.vm \
15 | WEB_PHP_TIMEOUT=600 \
16 | WEB_PHP_SOCKET=localhost:9000 \
17 | NGINX_CLIENT_MAX_BODY=50m \
18 | WEB_NO_CACHE_PATTERN="\.(css|js|gif|png|jpg|svg|json|xml)$"
19 | ENV NGINX_VERSION 1.19.1
20 | ENV NGX_BROTLI_COMMIT 25f86f0bac1101b6512135eac5f93c49c63609e3
21 | ENV XDEBUG_VERSION="3.0.0"
22 | ENV IS_CLI=false
23 | ENV IS_ALPINE=true
24 |
25 | COPY conf/ /opt/docker/
26 | # install dependencies
27 | RUN apk add --no-cache \
28 | aom-dev \
29 | bash-completion \
30 | curl \
31 | gd-dev \
32 | geoip-dev \
33 | git \
34 | gnupg1 \
35 | imagemagick \
36 | jpegoptim \
37 | less \
38 | libffi-dev \
39 | libgit2 \
40 | libwebp-tools \
41 | libxslt-dev \
42 | make \
43 | mariadb-client \
44 | openssh \
45 | openssl-dev \
46 | optipng \
47 | pcre-dev \
48 | pngquant \
49 | sshpass \
50 | sudo \
51 | supervisor \
52 | tree \
53 | unzip \
54 | vim \
55 | wget \
56 | zip \
57 | zlib-dev \
58 | && apk add --no-cache --virtual .build-deps \
59 | autoconf \
60 | automake \
61 | cargo \
62 | cmake \
63 | g++ \
64 | gcc \
65 | gettext \
66 | go \
67 | libc-dev \
68 | libtool \
69 | linux-headers \
70 | musl-dev \
71 | perl-dev \
72 | rust
73 |
74 |
75 | # Add groups and users
76 |
77 | RUN addgroup -S nginx \
78 | && adduser -D -S -h /var/cache/nginx -s /sbin/nologin -G nginx nginx
79 | RUN addgroup -g $APPLICATION_GID $APPLICATION_GROUP \
80 | && echo "%$APPLICATION_GROUP ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$APPLICATION_USER \
81 | && adduser -D -u $APPLICATION_UID -s /bin/bash -G $APPLICATION_GROUP $APPLICATION_USER \
82 | && addgroup $APPLICATION_USER nginx
83 |
84 | RUN mkdir -p /usr/src \
85 | && cd /usr/src \
86 | && git clone --recursive https://github.com/google/ngx_brotli.git \
87 | && cd ngx_brotli \
88 | && git submodule update --init --recursive \
89 | && cd deps/brotli \
90 | && mkdir out \
91 | && cd out \
92 | && cmake .. \
93 | && make -j 16 brotli \
94 | && cp brotli /usr/local/bin/brotli
95 | RUN cd /usr/src \
96 | && curl -fSL https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz -o nginx.tar.gz \
97 | && mkdir -p /usr/src \
98 | && tar -zxC /usr/src -f nginx.tar.gz \
99 | && rm nginx.tar.gz \
100 | && cd /usr/src/nginx-$NGINX_VERSION \
101 | && ls -la /usr/src/ngx_brotli \
102 | && CONFIG=" \
103 | --prefix=/etc/nginx \
104 | --sbin-path=/usr/sbin/nginx \
105 | --conf-path=/etc/nginx/nginx.conf \
106 | --error-log-path=/var/log/nginx/error.log \
107 | --http-log-path=/var/log/nginx/access.log \
108 | --pid-path=/var/run/nginx.pid \
109 | --lock-path=/var/run/nginx.lock \
110 | --http-client-body-temp-path=/var/cache/nginx/client_temp \
111 | --http-proxy-temp-path=/var/cache/nginx/proxy_temp \
112 | --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
113 | --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
114 | --http-scgi-temp-path=/var/cache/nginx/scgi_temp \
115 | --user=nginx \
116 | --group=nginx \
117 | --with-http_ssl_module \
118 | --with-http_realip_module \
119 | --with-http_addition_module \
120 | --with-http_sub_module \
121 | --with-http_dav_module \
122 | --with-http_flv_module \
123 | --with-http_mp4_module \
124 | --with-http_gunzip_module \
125 | --with-http_gzip_static_module \
126 | --with-http_random_index_module \
127 | --with-http_secure_link_module \
128 | --with-http_stub_status_module \
129 | --with-http_auth_request_module \
130 | --with-http_xslt_module=dynamic \
131 | --with-http_image_filter_module=dynamic \
132 | --with-http_geoip_module=dynamic \
133 | --with-http_perl_module=dynamic \
134 | --with-mail \
135 | --with-mail_ssl_module \
136 | --with-file-aio \
137 | --with-threads \
138 | --with-stream \
139 | --with-compat \
140 | --with-stream_ssl_module \
141 | --with-stream_realip_module \
142 | --with-http_slice_module \
143 | --with-http_v2_module \
144 | --with-debug \
145 | --add-dynamic-module=/usr/src/ngx_brotli \
146 | " \
147 | && ./configure $CONFIG \
148 | && make \
149 | && make install
150 |
151 | RUN mkdir -p /etc/nginx/modules-enabled/ \
152 | && mkdir -p /usr/lib/nginx/modules \
153 | && ln -s /etc/nginx/modules /usr/lib/nginx/modules \
154 | && cd /usr/src/nginx-$NGINX_VERSION \
155 | && cp objs/*.so /usr/lib/nginx/modules \
156 | && echo "load_module /usr/lib/nginx/modules/ngx_http_brotli_filter_module.so;" >> /etc/nginx/modules-enabled/brotli.conf \
157 | && echo "load_module /usr/lib/nginx/modules/ngx_http_brotli_static_module.so;" >> /etc/nginx/modules-enabled/brotli.conf \
158 | && ln -s /usr/lib/nginx/modules /etc/nginx/modules \
159 | && strip /usr/sbin/nginx* \
160 | && mv /usr/bin/envsubst /tmp/ \
161 | && runDeps="$( \
162 | scanelf --needed --nobanner /usr/sbin/nginx /usr/lib/nginx/modules/*.so /tmp/envsubst \
163 | | awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \
164 | | sort -u \
165 | | xargs -r apk info --installed \
166 | | sort -u \
167 | )" \
168 | && apk add --no-cache --virtual .nginx-rundeps tzdata $runDeps \
169 | && mv /tmp/envsubst /usr/local/bin/ \
170 | && ln -sf /dev/stdout /var/log/nginx/access.log \
171 | && ln -sf /dev/stderr /var/log/nginx/error.log \
172 | && mkdir -p /app/ \
173 | && touch /app/index.html \
174 | && echo "It Works!
" >> /app/index.html
175 |
176 | # hadolint ignore=DL3022
177 | COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/bin/
178 |
179 | RUN go get github.com/Kagami/go-avif \
180 | && cd /root/go/src/github.com/Kagami/go-avif \
181 | && make all \
182 | && mv /root/go/bin/avif /usr/local/bin/avif
183 |
184 | STOPSIGNAL SIGQUIT
185 |
186 | RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer
187 |
188 | RUN curl https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash > /root/.git-completion.bash \
189 | && curl https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh > /root/.git-prompt.sh \
190 | && curl https://raw.githubusercontent.com/ogham/exa/master/completions/completions.bash > /root/.completions.bash
191 |
192 | USER application
193 |
194 | RUN curl https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash > /home/$APPLICATION_USER/.git-completion.bash \
195 | && curl https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh > /home/$APPLICATION_USER/.git-prompt.sh \
196 | && curl https://raw.githubusercontent.com/ogham/exa/master/completions/completions.bash > /home/$APPLICATION_USER/.completions.bash
197 | RUN composer global require perftools/php-profiler && composer clear
198 | COPY user/* /home/$APPLICATION_USER/
199 | RUN echo "source ~/bashconfig.sh" >> ~/.bashrc
200 |
201 | USER root
202 | COPY user/* /root/
203 | RUN mkdir -p /opt/php-libs
204 | COPY php/* /opt/php-libs/files/
205 |
206 | RUN mv /opt/php-libs/files/opcache-jit.ini "$PHP_INI_DIR/conf.d/docker-php-opcache-jit.ini" \
207 | && install-php-extensions \
208 | xdebug-^3 \
209 | pcov \
210 | mongodb \
211 | zip \
212 | soap \
213 | gd \
214 | pcntl \
215 | && docker-php-ext-install ffi \
216 | && docker-php-ext-enable ffi
217 | RUN mv /opt/php-libs/files/pcov.ini "$PHP_INI_DIR/conf.d/docker-php-pcov.ini" \
218 | && mkdir /tmp/debug \
219 | && chmod -R 777 /tmp/debug \
220 | # && mkdir -p /opt/docker/profiler \
221 | # && mv /opt/php-libs/files/xhprof.ini "$PHP_INI_DIR/conf.d/docker-php-ext-xhprof.ini" \
222 | && echo "ffi.enable=preload" >> "$PHP_INI_DIR/conf.d/docker-php-ffi.ini"
223 |
224 | ENV \
225 | COMPOSER_HOME=/home/$APPLICATION_USER/.composer \
226 | POSTFIX_RELAYHOST="[global-mail]:1025" \
227 | PHP_DISPLAY_ERRORS="1" \
228 | PHP_MEMORY_LIMIT="-1" \
229 | TZ=Europe/Berlin
230 |
231 | WORKDIR /tmp
232 |
233 | ENV PATH=/usr/local/cargo/bin:$PATH
234 |
235 | RUN git clone https://github.com/ogham/exa \
236 | && cd exa \
237 | && cargo build --release \
238 | && mv target/release/exa /usr/local/bin/exa \
239 | && curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin/ \
240 | && rm -rf /tmp/exa
241 |
242 | # hadolint ignore=DL4001
243 | RUN wget https://github.com/dalance/amber/releases/download/v0.5.8/amber-v0.5.8-x86_64-lnx.zip \
244 | && unzip amber-v0.5.8-x86_64-lnx.zip \
245 | && rm amber-v0.5.8-x86_64-lnx.zip \
246 | && mv amb* /usr/local/bin/
247 |
248 | COPY entrypoint/entrypoint.sh /entrypoint
249 | COPY entrypoint/scripts /entrypoint.d/
250 | COPY bins/ /usr-bins/
251 | RUN chmod +x /entrypoint.d/*.sh /entrypoint /usr-bins/* \
252 | && mv /usr-bins/* /usr/local/bin/ \
253 | && mkdir -p /var/log/supervisord
254 |
255 |
256 | RUN apk del .build-deps .nginx-rundeps
257 |
258 |
259 |
260 | ENTRYPOINT ["/entrypoint"]
261 | EXPOSE 80 443 9003
262 |
263 | WORKDIR /app
264 |
265 |
--------------------------------------------------------------------------------
/php/opcache-jit.ini:
--------------------------------------------------------------------------------
1 | zend_extension=opcache.so
2 | opcache.enable=1
3 | opcache.enable_cli=1
4 | opcache.jit_buffer_size=32M
5 | opcache.jit=1235
6 |
--------------------------------------------------------------------------------
/php/pcov.ini:
--------------------------------------------------------------------------------
1 | pcov.enabled=0
2 | pcov.exclude='~vendor~'
3 | pcov.directory=/app/
4 |
--------------------------------------------------------------------------------
/php/profiler.php:
--------------------------------------------------------------------------------
1 | Profiler::PROFILER_TIDEWAYS_XHPROF,
22 | 'profiler.flags' => [
23 | ProfilingFlags::CPU,
24 | ProfilingFlags::MEMORY,
25 | ProfilingFlags::NO_BUILTINS,
26 | ProfilingFlags::NO_SPANS,
27 | ],
28 |
29 | 'save.handler' => Profiler::SAVER_FILE,
30 | 'save.handler.file' => array(
31 | // Appends jsonlines formatted data to this path
32 | 'filename' => getenv('PROFILING_FILE') ?: '/opt/docker/profiler/xhgui.data.jsonl',
33 | ),
34 |
35 | // Environment variables to exclude from profiling data
36 | 'profiler.exclude-env' => [
37 | 'APP_DATABASE_PASSWORD',
38 | 'PATH',
39 | ],
40 |
41 | 'profiler.options' => [
42 | ],
43 |
44 | /**
45 | * Determine whether profiler should run.
46 | * This default implementation just disables the profiler.
47 | * Override this with your custom logic in your config
48 | * @return bool
49 | */
50 | 'profiler.enable' => function () {
51 | return (isset($_COOKIE['XDEBUG_PROFILE']) || getenv('PROFILING_ENABLED'));
52 | },
53 |
54 | /**
55 | * Creates a simplified URL given a standard URL.
56 | * Does the following transformations:
57 | *
58 | * - Remove numeric values after =.
59 | *
60 | * @param string $url
61 | * @return string
62 | */
63 | 'profile.simple_url' => function($url) {
64 | return preg_replace('/=\d+/', '', $url);;
65 | },
66 | ];
67 |
68 | try {
69 | /**
70 | * The constructor will throw an exception if the environment
71 | * isn't fit for profiling (extensions missing, other problems)
72 | */
73 | $profiler = new Profiler($config);
74 |
75 | // The profiler itself checks whether it should be enabled
76 | // for request (executes lambda function from config)
77 | $profiler->enable();
78 |
79 | // shutdown handler collects and stores the data.
80 | $profiler->registerShutdownHandler();
81 | } catch (Exception $e){
82 | // throw away or log error about profiling instantiation failure
83 | }
84 |
--------------------------------------------------------------------------------
/php/xdebug.ini:
--------------------------------------------------------------------------------
1 | # @see https://3.xdebug.org/docs/all_settings
2 | xdebug.mode=profile,develop,coverage
3 | # xdebug.client_host =
4 | xdebug.client_port=9003
5 | xdebug.discover_client_host=1
6 | xdebug.start_with_request=default
7 | xdebug.idekey=PHPSTORM
8 | xdebug.cli_color=1
9 | xdebug.max_nesting_level=1000
10 | xdebug.output_dir=/tmp/debug
11 |
--------------------------------------------------------------------------------
/php/xhprof.ini:
--------------------------------------------------------------------------------
1 | #auto_prepend_file=/opt/php-libs/files/profiler.php
2 |
--------------------------------------------------------------------------------
/settings.toml:
--------------------------------------------------------------------------------
1 | template_path = "templates/"
2 | output_path = "Dockerfile"
3 | base_template = "template_dockerfile"
--------------------------------------------------------------------------------
/templates/dependencies.alpine.dockerfile:
--------------------------------------------------------------------------------
1 | # install dependencies
2 | RUN apk add --no-cache \
3 | aom-dev \
4 | bash-completion \
5 | curl \
6 | gd-dev \
7 | geoip-dev \
8 | git \
9 | gnupg1 \
10 | imagemagick \
11 | jpegoptim \
12 | less \
13 | libffi-dev \
14 | libgit2 \
15 | libwebp-tools \
16 | libxslt-dev \
17 | make \
18 | mariadb-client \
19 | openssh \
20 | openssl-dev \
21 | optipng \
22 | pcre-dev \
23 | pngquant \
24 | sshpass \
25 | sudo \
26 | supervisor \
27 | tree \
28 | unzip \
29 | vim \
30 | wget \
31 | zip \
32 | zlib-dev \
33 | && apk add --no-cache --virtual .build-deps \
34 | autoconf \
35 | automake \
36 | cargo \
37 | cmake \
38 | g++ \
39 | gcc \
40 | gettext \
41 | go \
42 | libc-dev \
43 | libtool \
44 | linux-headers \
45 | musl-dev \
46 | perl-dev \
47 | rust
48 |
--------------------------------------------------------------------------------
/templates/dependencies.debian.dockerfile:
--------------------------------------------------------------------------------
1 | # install dependencies
2 | RUN apt-get update && apt-get install -y --no-install-recommends \
3 | apt-transport-https \
4 | autoconf \
5 | automake \
6 | bash-completion \
7 | cmake \
8 | curl \
9 | g++ \
10 | gcc \
11 | gettext \
12 | git \
13 | gnupg1 \
14 | golang-go\
15 | imagemagick \
16 | jpegoptim \
17 | less \
18 | libaom-dev \
19 | libffi-dev \
20 | libgd-dev \
21 | libgeoip-dev \
22 | libgit2-dev \
23 | libpcre3 \
24 | libpcre3-dev \
25 | libperl-dev \
26 | libssl-dev \
27 | libtool \
28 | libwebp-dev \
29 | libxslt-dev \
30 | make \
31 | mariadb-client \
32 | openssh-client \
33 | openssl \
34 | optipng \
35 | pngquant \
36 | socat \
37 | sshpass \
38 | sudo \
39 | supervisor \
40 | tree \
41 | unzip \
42 | vim \
43 | wget \
44 | zip \
45 | && rm -rf /var/lib/apt/lists/* \
46 | && curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain stable -y
47 |
--------------------------------------------------------------------------------
/templates/docker.partial.dockerfile:
--------------------------------------------------------------------------------
1 | WORKDIR /tmp
2 |
3 | ENV PATH=/usr/local/cargo/bin:$PATH
4 |
5 | RUN git clone https://github.com/ogham/exa \
6 | && cd exa \ {{- if use_apk }}
7 | && cargo build --release \
8 | {{- else }}
9 | && /root/.cargo/bin/cargo build --release \
10 | {{- endif }}
11 | && mv target/release/exa /usr/local/bin/exa \
12 | && curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin/ \
13 | && rm -rf /tmp/exa
14 |
15 | # hadolint ignore=DL4001
16 | RUN wget https://github.com/dalance/amber/releases/download/v0.5.8/amber-v0.5.8-x86_64-lnx.zip \
17 | && unzip amber-v0.5.8-x86_64-lnx.zip \
18 | && rm amber-v0.5.8-x86_64-lnx.zip \
19 | && mv amb* /usr/local/bin/
20 |
21 | COPY entrypoint/entrypoint.sh /entrypoint
22 | COPY entrypoint/scripts /entrypoint.d/
23 | COPY bins/ /usr-bins/
24 | RUN chmod +x /entrypoint.d/*.sh /entrypoint /usr-bins/* \
25 | && mv /usr-bins/* /usr/local/bin/ \
26 | && mkdir -p /var/log/supervisord
27 |
28 | {{ if use_apk }}
29 | RUN apk del .build-deps .nginx-rundeps
30 | {{ else }}
31 | RUN rm -rf /var/lib/apt/lists/* \
32 | && apt-get remove -y \
33 | automake \
34 | cmake \
35 | g++ \
36 | gettext \
37 | golang-go\
38 | libtool \
39 | && /root/.cargo/bin/rustup self uninstall -y
40 | {{ endif }}
41 |
42 |
43 | ENTRYPOINT ["/entrypoint"]
44 |
45 | {{- if is_web }}
46 | EXPOSE 80 443 9003
47 | {{- endif }}
48 |
49 | WORKDIR /app
50 |
--------------------------------------------------------------------------------
/templates/nginx.partial.dockerfile:
--------------------------------------------------------------------------------
1 | RUN mkdir -p /usr/src \
2 | && cd /usr/src \
3 | && git clone --recursive https://github.com/google/ngx_brotli.git \
4 | && cd ngx_brotli \
5 | && git submodule update --init --recursive \
6 | && cd deps/brotli \
7 | && mkdir out \
8 | && cd out \
9 | && cmake .. \
10 | && make -j 16 brotli \
11 | && cp brotli /usr/local/bin/brotli
12 | RUN cd /usr/src \
13 | && curl -fSL https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz -o nginx.tar.gz \
14 | && mkdir -p /usr/src \
15 | && tar -zxC /usr/src -f nginx.tar.gz \
16 | && rm nginx.tar.gz \
17 | && cd /usr/src/nginx-$NGINX_VERSION \
18 | && ls -la /usr/src/ngx_brotli \
19 | && CONFIG=" \
20 | --prefix=/etc/nginx \
21 | --sbin-path=/usr/sbin/nginx \
22 | --conf-path=/etc/nginx/nginx.conf \
23 | --error-log-path=/var/log/nginx/error.log \
24 | --http-log-path=/var/log/nginx/access.log \
25 | --pid-path=/var/run/nginx.pid \
26 | --lock-path=/var/run/nginx.lock \
27 | --http-client-body-temp-path=/var/cache/nginx/client_temp \
28 | --http-proxy-temp-path=/var/cache/nginx/proxy_temp \
29 | --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
30 | --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
31 | --http-scgi-temp-path=/var/cache/nginx/scgi_temp \
32 | --user=nginx \
33 | --group=nginx \
34 | --with-http_ssl_module \
35 | --with-http_realip_module \
36 | --with-http_addition_module \
37 | --with-http_sub_module \
38 | --with-http_dav_module \
39 | --with-http_flv_module \
40 | --with-http_mp4_module \
41 | --with-http_gunzip_module \
42 | --with-http_gzip_static_module \
43 | --with-http_random_index_module \
44 | --with-http_secure_link_module \
45 | --with-http_stub_status_module \
46 | --with-http_auth_request_module \
47 | --with-http_xslt_module=dynamic \
48 | --with-http_image_filter_module=dynamic \
49 | --with-http_geoip_module=dynamic \
50 | --with-http_perl_module=dynamic \
51 | --with-mail \
52 | --with-mail_ssl_module \
53 | --with-file-aio \
54 | --with-threads \
55 | --with-stream \
56 | --with-compat \
57 | --with-stream_ssl_module \
58 | --with-stream_realip_module \
59 | --with-http_slice_module \
60 | --with-http_v2_module \
61 | --with-debug \
62 | --add-dynamic-module=/usr/src/ngx_brotli \
63 | " \
64 | && ./configure $CONFIG \
65 | && make \
66 | && make install
67 |
68 | RUN mkdir -p /etc/nginx/modules-enabled/ \
69 | && mkdir -p /usr/lib/nginx/modules \
70 | && ln -s /etc/nginx/modules /usr/lib/nginx/modules \
71 | && cd /usr/src/nginx-$NGINX_VERSION \
72 | && cp objs/*.so /usr/lib/nginx/modules \
73 | && echo "load_module /usr/lib/nginx/modules/ngx_http_brotli_filter_module.so;" >> /etc/nginx/modules-enabled/brotli.conf \
74 | && echo "load_module /usr/lib/nginx/modules/ngx_http_brotli_static_module.so;" >> /etc/nginx/modules-enabled/brotli.conf \
75 | && ln -s /usr/lib/nginx/modules /etc/nginx/modules \
76 | && strip /usr/sbin/nginx* \
77 | && mv /usr/bin/envsubst /tmp/ \ {{- if use_apk }}
78 | && runDeps="$( \
79 | scanelf --needed --nobanner /usr/sbin/nginx /usr/lib/nginx/modules/*.so /tmp/envsubst \
80 | | awk '\{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \
81 | | sort -u \
82 | | xargs -r apk info --installed \
83 | | sort -u \
84 | )" \
85 | && apk add --no-cache --virtual .nginx-rundeps tzdata $runDeps \ {{- else }}
86 | && apt-get update && apt-get install -y --no-install-recommends libperl-dev python3-pip tzdata \
87 | && rm -rf /var/lib/apt/lists/* \ {{- endif }}
88 | && mv /tmp/envsubst /usr/local/bin/ \
89 | && ln -sf /dev/stdout /var/log/nginx/access.log \
90 | && ln -sf /dev/stderr /var/log/nginx/error.log \
91 | && mkdir -p /app/ \
92 | && touch /app/index.html \
93 | && echo "It Works!
" >> /app/index.html
--------------------------------------------------------------------------------
/templates/template.dockerfile:
--------------------------------------------------------------------------------
1 | FROM {base.from}
2 |
3 | ENV TERM="xterm" \
4 | LANG="C.UTF-8" \
5 | LC_ALL="C.UTF-8"
6 | ENV DOCKER_CONF_HOME=/opt/docker/
7 | ENV APPLICATION_USER=application \
8 | APPLICATION_GROUP=application \
9 | APPLICATION_PATH=/app \
10 | APPLICATION_UID=1000 \
11 | APPLICATION_GID=1000 {{- if base.is_web }}
12 | ENV WEB_DOCUMENT_ROOT=/app \
13 | WEB_DOCUMENT_INDEX=index.php \
14 | WEB_ALIAS_DOMAIN=*.vm \
15 | WEB_PHP_TIMEOUT=600 \
16 | WEB_PHP_SOCKET=localhost:9000 \
17 | NGINX_CLIENT_MAX_BODY=50m \
18 | WEB_NO_CACHE_PATTERN="\.(css|js|gif|png|jpg|svg|json|xml)$"
19 | ENV NGINX_VERSION 1.19.1
20 | ENV NGX_BROTLI_COMMIT 25f86f0bac1101b6512135eac5f93c49c63609e3{{- endif }}
21 | {{ if is_dev }}ENV XDEBUG_VERSION="{base.envs.XDEBUG_VERSION}"{{ endif }}
22 | ENV IS_CLI={{- if base.is_web }}false{{- else }}true{{- endif }}
23 | ENV IS_ALPINE={{- if base.use_apk }}true{{- else }}false{{- endif }}
24 |
25 | COPY conf/ /opt/docker/
26 |
27 | {{- if base.use_apk }}
28 | {{ call dependencies_alpine_dockerfile with base }}
29 | {{- else }}
30 | {{ call dependencies_debian_dockerfile with base }}
31 | {{- endif }}
32 |
33 | # Add groups and users
34 | {{ if base.use_apk }}
35 | RUN addgroup -S nginx \
36 | && adduser -D -S -h /var/cache/nginx -s /sbin/nologin -G nginx nginx
37 | RUN addgroup -g $APPLICATION_GID $APPLICATION_GROUP \ {{- if is_dev }}
38 | && echo "%$APPLICATION_GROUP ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$APPLICATION_USER \ {{- endif }}
39 | && adduser -D -u $APPLICATION_UID -s /bin/bash -G $APPLICATION_GROUP $APPLICATION_USER {{- if base.is_web }} \
40 | && addgroup $APPLICATION_USER nginx {{- endif }}
41 | {{ else }}
42 | {{- if base.is_web }}
43 | RUN groupadd -g 103 nginx \
44 | && adduser --gecos "" --disabled-password --system --home /var/cache/nginx --shell /sbin/nologin --ingroup nginx nginx {{- endif }}
45 | RUN groupadd -g $APPLICATION_GID $APPLICATION_GROUP \ {{- if is_dev }}
46 | && echo "%$APPLICATION_GROUP ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$APPLICATION_USER \ {{- endif }}
47 | && adduser --gecos "" --disabled-password --uid $APPLICATION_UID --shell /bin/bash --ingroup $APPLICATION_GROUP $APPLICATION_USER {{- if base.is_web }} \
48 | && usermod -aG nginx $APPLICATION_USER {{- endif }}
49 | {{ endif }}
50 |
51 | {{- if base.is_web }}
52 | {{ call nginx_partial_dockerfile with base }}
53 | {{- endif }}
54 |
55 | # hadolint ignore=DL3022
56 | COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/bin/
57 |
58 | RUN go get github.com/Kagami/go-avif \
59 | && cd /root/go/src/github.com/Kagami/go-avif \
60 | && make all \
61 | && mv /root/go/bin/avif /usr/local/bin/avif
62 |
63 | STOPSIGNAL SIGQUIT
64 |
65 | RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer
66 |
67 | RUN curl https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash > /root/.git-completion.bash \
68 | && curl https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh > /root/.git-prompt.sh \
69 | && curl https://raw.githubusercontent.com/ogham/exa/master/completions/completions.bash > /root/.completions.bash
70 |
71 | USER application
72 |
73 | RUN curl https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash > /home/$APPLICATION_USER/.git-completion.bash \
74 | && curl https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh > /home/$APPLICATION_USER/.git-prompt.sh \
75 | && curl https://raw.githubusercontent.com/ogham/exa/master/completions/completions.bash > /home/$APPLICATION_USER/.completions.bash
76 | RUN composer global require perftools/php-profiler && composer clear
77 | COPY user/* /home/$APPLICATION_USER/
78 | RUN echo "source ~/bashconfig.sh" >> ~/.bashrc
79 |
80 | USER root
81 | COPY user/* /root/
82 | RUN mkdir -p /opt/php-libs
83 | COPY php/* /opt/php-libs/files/
84 |
85 | RUN mv /opt/php-libs/files/opcache-jit.ini "$PHP_INI_DIR/conf.d/docker-php-opcache-jit.ini" \
86 | && install-php-extensions \ {{- if is_dev }}
87 | xdebug-^3 \
88 | pcov \ {{- endif }}
89 | mongodb \
90 | zip \
91 | soap \
92 | gd \
93 | pcntl \
94 | && docker-php-ext-install ffi \
95 | && docker-php-ext-enable ffi
96 |
97 | {{- if is_dev }}
98 | RUN mv /opt/php-libs/files/pcov.ini "$PHP_INI_DIR/conf.d/docker-php-pcov.ini" \
99 | && mkdir /tmp/debug \
100 | && chmod -R 777 /tmp/debug \
101 | # && mkdir -p /opt/docker/profiler \
102 | # && mv /opt/php-libs/files/xhprof.ini "$PHP_INI_DIR/conf.d/docker-php-ext-xhprof.ini" \
103 | && echo "ffi.enable=preload" >> "$PHP_INI_DIR/conf.d/docker-php-ffi.ini"
104 | {{- endif }}
105 |
106 | ENV \
107 | COMPOSER_HOME=/home/$APPLICATION_USER/.composer \
108 | POSTFIX_RELAYHOST="[global-mail]:1025" \
109 | PHP_DISPLAY_ERRORS="1" \
110 | PHP_MEMORY_LIMIT="-1" \
111 | TZ=Europe/Berlin
112 |
113 | {{ call docker_partial_dockerfile with base }}
114 |
--------------------------------------------------------------------------------
/user/.vimrc:
--------------------------------------------------------------------------------
1 | filetype indent plugin on
2 | syntax on
3 | set hidden
4 |
--------------------------------------------------------------------------------
/user/bashconfig.sh:
--------------------------------------------------------------------------------
1 | export LS_COLORS="${LS_COLORS}di=1;34:"
2 | export EXA_COLORS="da=1;34:gm=1;34"
3 | alias ls='exa'
4 | alias ll='ls -alh --git --header --group'
5 | export PATH=$PATH:~/.composer/vendor/bin:./bin:./vendor/bin:./node_modules/.bin:/usr/local/cargo/bin
6 | source ~/.git-completion.bash
7 | source ~/.git-prompt.sh
8 | source ~/.completions.bash
9 |
10 | is_root() {
11 | return $(id -u)
12 | }
13 |
14 | has_sudo() {
15 | local prompt
16 |
17 | prompt=$(sudo -nv 2>&1)
18 | if [ $? -eq 0 ] || is_root; then
19 | return 1
20 | fi
21 | return 0
22 | }
23 |
24 | # for more information on this: https://github.com/pluswerk/php-dev/blob/master/.additional_bashrc.sh
25 | CONTAINER_ID=$(basename $(cat /proc/1/cpuset))
26 | export HOST_DISPLAY_NAME=$HOSTNAME
27 |
28 | if has_sudo -eq 1 && [ sudo docker ps -q ] &>/dev/null; then
29 | DOCKER_COMPOSE_PROJECT=$(sudo docker inspect ${CONTAINER_ID} | grep '"com.docker.compose.project":' | awk '{print $2}' | tr -d '"' | tr -d ',')
30 | export NODE_CONTAINER=$(sudo docker ps -f "name=${DOCKER_COMPOSE_PROJECT}_node_1" --format {{.Names}})
31 | export HOST_DISPLAY_NAME=$(sudo docker inspect ${CONTAINER_ID} --format='{{.Name}}')
32 | export HOST_DISPLAY_NAME=${HOST_DISPLAY_NAME:1}
33 |
34 | alias node_exec='sudo docker exec -u $(id -u):$(id -g) -w $(pwd) -it ${NODE_CONTAINER}'
35 | alias node_root_exec='sudo docker exec -w $(pwd) -it ${NODE_CONTAINER}'
36 |
37 | alias node='node_exec node'
38 | alias npm='node_exec npm'
39 | alias npx='node_exec npx'
40 | alias yarn='node_exec yarn'
41 | fi
42 | export HOST_DISPLAY_NAME=$HOSTNAME
43 |
44 | if [[ $CONTAINER_ID != ${HOSTNAME}* ]]; then
45 | export HOST_DISPLAY_NAME=$HOSTNAME
46 | fi
47 |
48 | PS1='\033]2;'$(pwd)'\007\[\e[0;36m\][\[\e[1;31m\]\u\[\e[0;36m\]@\[\e[1;34m\]$HOST_DISPLAY_NAME\[\e[0;36m\]: \[\e[0m\]\w\[\e[0;36m\]]\[\e[0m\]\$\[\e[1;32m\]\s\[\e[0;33m\]$(__git_ps1)\[\e[0;36m\]> \[\e[0m\]\n$ '
49 |
50 | eval `ssh-agent -s`
51 | if [ -z "$SSH_AUTH_SOCK" ]; then
52 | ssh-add -t 604800 ~/.ssh/id_rsa
53 | else
54 | ssh-add
55 | fi
56 |
57 | export EDITOR=vim
58 |
59 | ## this extracts pretty much any archive
60 | function extract() {
61 | if [ -f $1 ]; then
62 | case $1 in
63 | *.tar.bz2) tar xvjf $1 ;;
64 | *.tar.gz) tar xvzf $1 ;;
65 | *.bz2) bunzip2 $1 ;;
66 | *.rar) unrar x $1 ;;
67 | *.gz) gunzip $1 ;;
68 | *.tar) tar xvf $1 ;;
69 | *.tbz2) tar xvjf $1 ;;
70 | *.tgz) tar xvzf $1 ;;
71 | *.zip) unzip $1 ;;
72 | *.Z) uncompress $1 ;;
73 | *.7z) 7z x $1 ;;
74 | *) echo "'$1' cannot be extracted via >extract<" ;;
75 | esac
76 | else
77 | echo "'$1' is not a valid file!"
78 | fi
79 | }
80 |
81 | function xdebug-enable() {
82 | xdebug-mode "profile,develop,coverage"
83 | }
84 |
85 | function xdebug-debug() {
86 | xdebug-mode "debug,develop"
87 | }
88 |
89 | function xdebug-disable() {
90 | xdebug-mode "off"
91 | }
--------------------------------------------------------------------------------