├── data ├── prometheus │ └── .gitignore ├── mongo │ └── .gitignore ├── mysql │ └── .gitignore ├── composer │ └── .gitignore └── grafana │ └── .gitignore ├── .dockerignore ├── config ├── lua │ ├── waf │ │ ├── wafconf │ │ │ ├── whiteurl │ │ │ ├── white-user-agent │ │ │ ├── user-agent │ │ │ ├── url │ │ │ ├── cookie │ │ │ ├── post │ │ │ └── args │ │ ├── config.lua │ │ ├── waf.lua │ │ └── init.lua │ └── test │ │ ├── http.lua │ │ ├── redis.lua │ │ └── mysql.lua ├── sentry │ ├── .gitignore │ └── Dockerfile ├── redis │ └── Dockerfile ├── mongodb │ └── Dockerfile ├── nginx │ ├── conf.d │ │ ├── .gitignore │ │ ├── certs │ │ │ └── localhost │ │ │ │ ├── server.csr │ │ │ │ ├── gencert.sh │ │ │ │ ├── server.crt │ │ │ │ ├── server.key │ │ │ │ └── server.origin.key │ │ ├── lua.conf │ │ ├── localhost.conf │ │ └── localhost_https.conf │ ├── Dockerfile │ └── nginx.conf ├── golang │ └── Dockerfile ├── node │ └── Dockerfile ├── php │ ├── extensions │ │ ├── redis-4.3.0.tgz │ │ ├── xdebug-2.6.1.tgz │ │ ├── install-composer.sh │ │ ├── php.sh │ │ └── install.sh │ ├── Dockerfile │ ├── php-fpm.conf │ └── seccomp.json ├── postgres │ └── Dockerfile ├── mysql │ ├── Dockerfile │ └── mysql.cnf ├── yapi │ ├── entrypoint.sh │ ├── config.json │ ├── Dockerfile │ └── wait-for-it.sh ├── caddy │ ├── Dockerfile │ ├── Caddyfile │ └── vhosts │ │ └── localhost ├── grafana │ ├── prometheus.yml │ └── grafana.ini └── ubuntu │ └── Dockerfile ├── logs ├── caddy │ └── .gitignore ├── nginx │ └── .gitignore ├── php │ └── .gitignore └── letsencrypt │ └── .gitignore ├── www └── localhost │ ├── .user.ini │ ├── tools │ └── adminer.php.bak │ └── index.php ├── .gitattributes ├── .gitignore ├── zdc.bat ├── LICENSE ├── docker.md ├── .env.example ├── README.md ├── docker-compose.yml.example └── run.sh /data/prometheus/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | log/ 2 | mysql/ 3 | www/ -------------------------------------------------------------------------------- /data/mongo/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /data/mysql/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /config/lua/waf/wafconf/whiteurl: -------------------------------------------------------------------------------- 1 | ^/123/$ 2 | -------------------------------------------------------------------------------- /logs/caddy/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /logs/nginx/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /logs/php/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /config/lua/waf/wafconf/white-user-agent: -------------------------------------------------------------------------------- 1 | (baidu) 2 | -------------------------------------------------------------------------------- /logs/letsencrypt/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /config/sentry/.gitignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /data/composer/.gitignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /data/grafana/.gitignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /www/localhost/.user.ini: -------------------------------------------------------------------------------- 1 | open_basedir=/var/www/html/localhost:/tmp/:/proc/ 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | 3 | *.png binary 4 | *.jpg binary 5 | *.tgz binary -------------------------------------------------------------------------------- /config/redis/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG REDIS_IMAGES 2 | 3 | FROM ${REDIS_IMAGES} 4 | 5 | -------------------------------------------------------------------------------- /config/mongodb/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG MONGODB_IMAGES 2 | FROM ${MONGODB_IMAGES} 3 | 4 | 5 | -------------------------------------------------------------------------------- /config/nginx/conf.d/.gitignore: -------------------------------------------------------------------------------- 1 | !.gitignore 2 | !localhost.conf 3 | !localhost_https.conf 4 | -------------------------------------------------------------------------------- /config/golang/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG GO_IMAGES 2 | FROM ${GO_IMAGES} 3 | 4 | WORKDIR /var/www/html 5 | -------------------------------------------------------------------------------- /config/node/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG NODE_IMAGES 2 | FROM ${NODE_IMAGES} 3 | 4 | WORKDIR /var/www/html 5 | -------------------------------------------------------------------------------- /config/nginx/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG NGINX_IMAGES 2 | FROM ${NGINX_IMAGES} 3 | 4 | WORKDIR /var/www/html 5 | -------------------------------------------------------------------------------- /config/sentry/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG SENTRY_IMAGES 2 | FROM ${SENTRY_IMAGES} 3 | 4 | ARG SENTRY_REDIS_HOST 5 | -------------------------------------------------------------------------------- /www/localhost/tools/adminer.php.bak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sohaha/zls-docker/HEAD/www/localhost/tools/adminer.php.bak -------------------------------------------------------------------------------- /config/php/extensions/redis-4.3.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sohaha/zls-docker/HEAD/config/php/extensions/redis-4.3.0.tgz -------------------------------------------------------------------------------- /config/postgres/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG POSTGRES_IMAGES 2 | FROM ${POSTGRES_IMAGES} 3 | 4 | CMD ["postgres"] 5 | 6 | EXPOSE 5432 7 | -------------------------------------------------------------------------------- /config/php/extensions/xdebug-2.6.1.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sohaha/zls-docker/HEAD/config/php/extensions/xdebug-2.6.1.tgz -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .env 3 | .idea/ 4 | .vscode/ 5 | tmp/ 6 | !www/localhost/ 7 | docker-compose.yml 8 | www/ 9 | data/ 10 | -------------------------------------------------------------------------------- /config/lua/waf/wafconf/user-agent: -------------------------------------------------------------------------------- 1 | (HTTrack|harvest|audit|dirbuster|pangolin|nmap|sqln|-scan|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|PycURL|zmeu|BabyKrokodil|netsparker|httperf|bench| SF/) 2 | -------------------------------------------------------------------------------- /config/mysql/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG MYSQL_IMAGES 2 | FROM ${MYSQL_IMAGES} 3 | 4 | # mysql backup scripts using crontab 5 | # COPY ./scripts/ /data/mysql/backup/scripts/ 6 | # RUN crontab /data/mysql/backup/scripts/crontabfile 7 | # RUN service cron start 8 | -------------------------------------------------------------------------------- /config/yapi/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | cd ${VENDORS} 3 | if [ ! -e "init.lock" ] 4 | then 5 | cd ${VENDORS} 6 | yapi install -v ${YAPI_VERSION} 7 | touch init.lock 8 | fi 9 | 10 | cd ${VENDORS} 11 | # 先判断有没有CMD指定路径 12 | if [ $1 ] 13 | then 14 | node $i 15 | else 16 | node server/app.js 17 | fi -------------------------------------------------------------------------------- /config/caddy/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG CADDY_IMAGES 2 | 3 | FROM ${CADDY_IMAGES} AS builder 4 | 5 | # RUN go env -w GOPROXY=https://goproxy.cn,direct && xcaddy build --with github.com/caddy-dns/dnspod@latest 6 | 7 | 8 | FROM ${CADDY_IMAGES} 9 | 10 | WORKDIR /var/www/html 11 | 12 | # COPY --from=builder /usr/bin/caddy /usr/bin/caddy -------------------------------------------------------------------------------- /config/lua/waf/wafconf/url: -------------------------------------------------------------------------------- 1 | \.(svn|git|htaccess|bash_history|DS_Store) 2 | \.(bak|inc|old|mdb|sql|backup|java|class)$ 3 | (vhost|bbs|host|wwwroot|www|site|root|hytop|flashfxp).*\.rar 4 | (phpmyadmin|jmx-console|jmxinvokerservlet) 5 | java\.lang 6 | /(attachments|upimg|images|css|uploadfiles|html|uploads|templets|static|template|data|inc|forumdata|upload|includes|cache|avatar)/(\w+).(php|jsp) 7 | -------------------------------------------------------------------------------- /config/caddy/Caddyfile: -------------------------------------------------------------------------------- 1 | 2 | import ./vhosts/* 3 | 4 | # https://73zls.com { 5 | # tls caddy@caddy.com 6 | # root * /var/www/html/xxx/public 7 | # file_server 8 | # proxy / 127.0.0.1:20000 9 | # } 10 | 11 | # http://73zls.com 12 | # { 13 | # redir https://73zls.com{url} 14 | # } 15 | 16 | # Refer to the Caddy docs for more information: 17 | # https://caddyserver.com/docs/caddyfile 18 | -------------------------------------------------------------------------------- /config/grafana/prometheus.yml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 60s 3 | evaluation_interval: 60s 4 | 5 | scrape_configs: 6 | - job_name: prometheus 7 | static_configs: 8 | - targets: ['localhost:9090'] 9 | labels: 10 | instance: prometheus 11 | 12 | - job_name: mysqld 13 | static_configs: 14 | - targets: ['mysqlexporter:9104'] 15 | 16 | - job_name: 'node' 17 | static_configs: 18 | - targets: ['nodeexporter:9100'] -------------------------------------------------------------------------------- /config/yapi/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "port": "8005", 3 | "adminAccount": "admin@admin.com", 4 | "db": { 5 | "servername": "mongodb", 6 | "DATABASE": "yapi", 7 | "port": 27017, 8 | "user": "yapi", 9 | "pass": "73zls666" 10 | }, 11 | "mail": { 12 | "enable": false, 13 | "host": "smtp.163.com", 14 | "port": 465, 15 | "from": "***@163.com", 16 | "auth": { 17 | "user": "***@163.com", 18 | "pass": "*****" 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /config/php/extensions/install-composer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "---------- Install composer ----------" 4 | 5 | isChina=$(curl --silent "cip.cc" | grep "中国") 6 | isComposerURL="https://github.com/composer/composer/releases/download/${COMPOSER_VERSION}/composer.phar" 7 | if [[ -n $isChina || "" == $COMPOSER_VERSION ]]; then 8 | isComposerURL="https://mirrors.aliyun.com/composer/composer.phar" 9 | fi 10 | 11 | wget ${isComposerURL} \ 12 | && chmod a+rwx composer.phar \ 13 | && mv composer.phar /usr/local/bin/composer \ 14 | && composer config -l -g -------------------------------------------------------------------------------- /config/caddy/vhosts/localhost: -------------------------------------------------------------------------------- 1 | :80 { 2 | # Set this path to your site's directory. 3 | root * /var/www/html/localhost 4 | 5 | # compress 6 | encode gzip 7 | 8 | # Enable the static file server. 9 | file_server { 10 | precompressed br gzip 11 | hide .git .git/ .git/* .git* .gitignore 12 | } 13 | 14 | # Redirect. 15 | # redir https://www.73zls.com{uri} 16 | 17 | # Another common task is to set up a reverse proxy: 18 | # reverse_proxy localhost:8080 19 | 20 | # Or serve a PHP site through php-fpm: 21 | php_fastcgi php:9000 22 | 23 | file_server 24 | } 25 | -------------------------------------------------------------------------------- /config/ubuntu/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG UBUNTU_IMAGES 2 | FROM ${UBUNTU_IMAGES} 3 | 4 | WORKDIR /var/www/html 5 | 6 | ENV GOUP_GO_HOST=golang.google.cn 7 | ENV GOUP_UPDATE_ROOT=https://github.com/owenthereal/goup/releases/latest/download 8 | ENV GOPROXY=https://goproxy.cn 9 | 10 | ENV PATH=$PATH:/root/.go/bin:/root/.go/current/bin 11 | 12 | RUN sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list && apt-get clean 13 | 14 | # RUN apt update && apt install curl -y 15 | # curl -sSf https://raw.githubusercontent.com/owenthereal/goup/master/install.sh | sh -s -- '--skip-prompt' 16 | 17 | # apt install -y manpages-dev 18 | # RUN tail -F /dev/null 19 | 20 | # gcc 21 | # apt update && apt install -y gcc build-essential -------------------------------------------------------------------------------- /config/nginx/conf.d/certs/localhost/server.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIBrzCCARgCAQAwbzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBE1hcnMxEzARBgNV 3 | BAcMCmlUcmFuc3dhcnAxEzARBgNVBAoMCmlUcmFuc3dhcnAxEzARBgNVBAsMCmlU 4 | cmFuc3dhcnAxEjAQBgNVBAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOB 5 | jQAwgYkCgYEAuM697WuhKWhxoY7mQHToThWbQZN1kss8omrJzo9TJbQzASpOGDBa 6 | hRZn1HQxZiorN7XNuQopF0He5kVb5ge3smvNVyeFoKzSHgEV9Q6owKaSJPX2LpTw 7 | 6r/uuOA93jnosz5/R5IDrErfKt57n5QJ4PRS9zZ6op1Yq5iTc0jhtlECAwEAAaAA 8 | MA0GCSqGSIb3DQEBCwUAA4GBAGmV0Q7YkEux+0DvpzhAGhi6mGs097vKMtAUUPCk 9 | A7ETj7XWRR+49VMzG0IzE3Y3mKMi63m34mxnmDmJvZX5UWB+ijc33609hGnzNW8P 10 | KgtB1EJBb7lymP59Ja/XFj95m14E3ZDDPFgdES8jT0AjQHHAu9r1GYHT57tx2fOj 11 | AP5x 12 | -----END CERTIFICATE REQUEST----- 13 | -------------------------------------------------------------------------------- /config/lua/waf/wafconf/cookie: -------------------------------------------------------------------------------- 1 | \.\./ 2 | \:\$ 3 | \$\{ 4 | select.+(from|limit) 5 | (?:(union(.*?)select)) 6 | having|rongjitest 7 | sleep\((\s*)(\d*)(\s*)\) 8 | benchmark\((.*)\,(.*)\) 9 | base64_decode\( 10 | (?:from\W+information_schema\W) 11 | (?:(?:current_)user|database|schema|connection_id)\s*\( 12 | (?:etc\/\W*passwd) 13 | into(\s+)+(?:dump|out)file\s* 14 | group\s+by.+\( 15 | xwork.MethodAccessor 16 | (?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\( 17 | xwork\.MethodAccessor 18 | (gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\/ 19 | java\.lang 20 | \$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\[ 21 | -------------------------------------------------------------------------------- /config/nginx/conf.d/certs/localhost/gencert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # create self-signed server certificate: 4 | 5 | read -p "Enter your domain [www.example.com]: " DOMAIN 6 | 7 | echo "Create server key..." 8 | 9 | openssl genrsa -des3 -out $DOMAIN.key 1024 10 | 11 | echo "Create server certificate signing request..." 12 | 13 | SUBJECT="/C=US/ST=Mars/L=iTranswarp/O=iTranswarp/OU=iTranswarp/CN=$DOMAIN" 14 | 15 | openssl req -new -subj $SUBJECT -key $DOMAIN.key -out $DOMAIN.csr 16 | 17 | echo "Remove password..." 18 | 19 | mv $DOMAIN.key $DOMAIN.origin.key 20 | openssl rsa -in $DOMAIN.origin.key -out $DOMAIN.key 21 | 22 | echo "Sign SSL certificate..." 23 | 24 | openssl x509 -req -days 3650 -in $DOMAIN.csr -signkey $DOMAIN.key -out $DOMAIN.crt 25 | 26 | echo "Done!" 27 | -------------------------------------------------------------------------------- /config/lua/waf/wafconf/post: -------------------------------------------------------------------------------- 1 | select.+(from|limit) 2 | (?:(union(.*?)select)) 3 | having|rongjitest 4 | sleep\((\s*)(\d*)(\s*)\) 5 | benchmark\((.*)\,(.*)\) 6 | base64_decode\( 7 | (?:from\W+information_schema\W) 8 | (?:(?:current_)user|database|schema|connection_id)\s*\( 9 | (?:etc\/\W*passwd) 10 | into(\s+)+(?:dump|out)file\s* 11 | group\s+by.+\( 12 | xwork.MethodAccessor 13 | (?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\( 14 | xwork\.MethodAccessor 15 | (gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\/ 16 | java\.lang 17 | \$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\[ 18 | \<(iframe|script|body|img|layer|div|meta|style|base|object|input) 19 | (onmouseover|onerror|onload)\= 20 | -------------------------------------------------------------------------------- /zdc.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | set mycd=%cd% 3 | cd /d %~dp0 4 | set c=%1 5 | set a=%* 6 | call :CurDIR "%cd%" 7 | goto :eof 8 | :CurDIR 9 | set _dockerDir=%~nx1 10 | set volume=--volume %mycd%:/var/www/html 11 | 12 | if %c% == php (docker run --tty --interactive --rm --cap-add SYS_PTRACE %volume% --workdir /var/www/html "%_dockerDir%_php" %a%) 13 | 14 | if %c% == composer (docker run --tty --interactive --rm --cap-add SYS_PTRACE %volume% --workdir /var/www/html "%_dockerDir%_php" %a%) 15 | 16 | if %c% == node (docker run --tty --interactive --rm --cap-add SYS_PTRACE %volume% --workdir /var/www/html "%_dockerDir%_node" %a%) 17 | 18 | if %c% == npm (docker run --tty --interactive --rm --cap-add SYS_PTRACE %volume% --workdir /var/www/html "%_dockerDir%_node" %a%) 19 | 20 | if %c% == up (docker-compose up -d nginx) 21 | 22 | cd /d %mycd% -------------------------------------------------------------------------------- /config/php/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG PHP_IMAGES 2 | FROM ${PHP_IMAGES} 3 | 4 | ARG PHP_EXTENSIONS 5 | ARG MORE_EXTENSION_INSTALLER 6 | ARG ALPINE_REPOSITORIES 7 | ARG COMPOSER_VERSION 8 | ARG COMPOSER_PACKAGIST 9 | 10 | COPY ./extensions /tmp/extensions 11 | 12 | WORKDIR /tmp/extensions 13 | 14 | ENV EXTENSIONS=",${PHP_EXTENSIONS}," 15 | ENV MC="-j$(nproc)" 16 | ENV COMPOSER_HOME="/composer" 17 | ENV COMPOSER_ALLOW_SUPERUSER=1 18 | ENV COMPOSER_PACKAGIST="${COMPOSER_PACKAGIST}" 19 | 20 | RUN export MC="-j$(nproc)" \ 21 | && chmod +x install.sh \ 22 | && chmod +x install-composer.sh \ 23 | && chmod +x "${MORE_EXTENSION_INSTALLER}"\ 24 | && sh install.sh \ 25 | && sh "${MORE_EXTENSION_INSTALLER}" \ 26 | && php -v \ 27 | && php -m \ 28 | && sh install-composer.sh \ 29 | && rm -rf /tmp/extensions 30 | 31 | WORKDIR /var/www/html 32 | -------------------------------------------------------------------------------- /config/lua/waf/wafconf/args: -------------------------------------------------------------------------------- 1 | \.\./ 2 | \:\$ 3 | \$\{ 4 | select.+(from|limit) 5 | (?:(union(.*?)select)) 6 | having|rongjitest 7 | sleep\((\s*)(\d*)(\s*)\) 8 | benchmark\((.*)\,(.*)\) 9 | base64_decode\( 10 | (?:from\W+information_schema\W) 11 | (?:(?:current_)user|database|schema|connection_id)\s*\( 12 | (?:etc\/\W*passwd) 13 | into(\s+)+(?:dump|out)file\s* 14 | group\s+by.+\( 15 | xwork.MethodAccessor 16 | (?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\( 17 | xwork\.MethodAccessor 18 | (gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\/ 19 | java\.lang 20 | \$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\[ 21 | \<(iframe|script|body|img|layer|div|meta|style|base|object|input) 22 | (onmouseover|onerror|onload)\= 23 | -------------------------------------------------------------------------------- /config/nginx/conf.d/certs/localhost/server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICVTCCAb4CCQCz53tsf+lJiTANBgkqhkiG9w0BAQsFADBvMQswCQYDVQQGEwJV 3 | UzENMAsGA1UECAwETWFyczETMBEGA1UEBwwKaVRyYW5zd2FycDETMBEGA1UECgwK 4 | aVRyYW5zd2FycDETMBEGA1UECwwKaVRyYW5zd2FycDESMBAGA1UEAwwJbG9jYWxo 5 | b3N0MB4XDTE5MDgwMTAzMzk1M1oXDTI5MDcyOTAzMzk1M1owbzELMAkGA1UEBhMC 6 | VVMxDTALBgNVBAgMBE1hcnMxEzARBgNVBAcMCmlUcmFuc3dhcnAxEzARBgNVBAoM 7 | CmlUcmFuc3dhcnAxEzARBgNVBAsMCmlUcmFuc3dhcnAxEjAQBgNVBAMMCWxvY2Fs 8 | aG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuM697WuhKWhxoY7mQHTo 9 | ThWbQZN1kss8omrJzo9TJbQzASpOGDBahRZn1HQxZiorN7XNuQopF0He5kVb5ge3 10 | smvNVyeFoKzSHgEV9Q6owKaSJPX2LpTw6r/uuOA93jnosz5/R5IDrErfKt57n5QJ 11 | 4PRS9zZ6op1Yq5iTc0jhtlECAwEAATANBgkqhkiG9w0BAQsFAAOBgQA28kayGliM 12 | 0OBXcKHoPNeGnpOvPjekN6jyistjYjdiYyNiLFIw2Mt2rQWiXYQq9Vz1T0P7EQO5 13 | udFoV9aTgu0jORbTNGgkLE6EzsDX4xDLR0knodLxi/b6svzYlwEmcsBmpa5GEzC6 14 | P1eZQ/VUthEvfxQCmqbUzl3C1vz7fRrXZg== 15 | -----END CERTIFICATE----- 16 | -------------------------------------------------------------------------------- /config/nginx/conf.d/certs/localhost/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXAIBAAKBgQC4zr3ta6EpaHGhjuZAdOhOFZtBk3WSyzyiasnOj1MltDMBKk4Y 3 | MFqFFmfUdDFmKis3tc25CikXQd7mRVvmB7eya81XJ4WgrNIeARX1DqjAppIk9fYu 4 | lPDqv+644D3eOeizPn9HkgOsSt8q3nuflAng9FL3NnqinVirmJNzSOG2UQIDAQAB 5 | AoGAdj8qPRhptQHz+uhhIQrsfNHMVkgQqY1Kza1AVN9V10EWhX9ZGpcNxCwS4Vg7 6 | J2CB6JJ2ABilNBFcmr/0ThnQCc09gGk2z1qeLfqlmMOWY7bjGqCCEv3yCZFddHTy 7 | 98JenFiz6CAxkLcxbDSyUk/IP2reEvc7r43njk6kWMwlBqUCQQDrnz1rHS3021rS 8 | mciVbeSHJjQOgKGx/PHpfrtESjjPG2KiqnLCNDUY9B4/bxy1WqXi9N9TSphYOB4I 9 | xK1ZkUd7AkEAyMpzfKoiWy7uQNVF+qFMrbMBhKVWSJOHUCoaGtERwQnlc8ZrIk2A 10 | 33OHnIY4ULQn/sTPgUWlnRllitvSrEOpowJAZFqxZRLLhRN8TmCTbxmcEPfzig29 11 | ULqkKkgA6KgYJBXM3+1q7U4hI1yuGWRwvMk8CDs1dxs5YbGdESz7jD91SwJAXGjg 12 | cdWTbkfRG0GMrWai9aZW4od9iHVtZzWZQhJKi39UfM4q7GSjFTQEi8MyE+J2LcjC 13 | f4pgSEcx9pBpCyMw5QJBAIUBRFzvSdkMzzssj0ti9BZiXuvcylAQ3fp8yXoJrZr+ 14 | dBKaX8JbftMKoidGdKFV/+J+olYMwtMs0c54z/AVxuE= 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /config/nginx/conf.d/certs/localhost/server.origin.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: DES-EDE3-CBC,7B88CF20C2DD2972 4 | 5 | ztUpEzHGRNQ2xSRyWR/pwOFvXPVbmt+Fiv1ayiJRKaxS8aDtOxv0izk37EOU66Wk 6 | ilD+JjHx5iWcFiNRBKRsfQ983mS35bV6Xo37bLnEYtClxAJChUjnmRGT2KHSo7ye 7 | 9lE5RyDnTqJFR/rz6QfLqrVyWYwJmFpaJqkSd7uFB92Eo8GjIoCccH7uZwCn05ur 8 | /kIUVVg5XZ7O7H+8FI1MAOUmkZipwpRDN7A07A2NW5bUpZ6cp03eBkJEOOfrF9C3 9 | v59n2Ei/eFgFaJsV8hCj3tBzEcokFL+CKhQl8PL3oOULIzC36WtEOlg3dtK3Jorm 10 | 9X9pEurWKOh0DCnNugW0vQGUfD26eUGn2USXhqkFxkV58WLVfmT414KrsGtJfISO 11 | H2DHtj822Z/VYOPaDXMoROhB8RYtdE8s1HbAUMDxknt4JVIR9rNRiaPl9fkXCrA0 12 | LBuRaXF9A821L+W/BZia2ahtAJ4bfQXgYB08n1T/VBp4VBjQY80DkK3Ou0QuOsuF 13 | EJHXR96pM0ACDShhKppxXK0ozZst/XLUJ/6w3UtHRjL9zyx8Fq040EEjEayY8cqM 14 | 2iWd1OHtDI44g+Xb6X0h3Mk1e3gXmc8Wlq80wVqxOaZ8rGIQ+epGYZGBK3sI7wrL 15 | wiDDKrwmQqbsJcg8sFB+THhEtgIZGfWh96CI/27n4mzWNm+Ys2NzjqiM5QhN/du9 16 | rLIaVYHldzkgnkMW+w1EXi82tpbQKI5Kw9jolF8fPSYYJroT7xe/Kuuim2z0AEWD 17 | SLQCB9t4zGdzOFGlZ+EucPaMepFeEb0p9xMKXI0ENZIR+Cno/OQFQA== 18 | -----END RSA PRIVATE KEY----- 19 | -------------------------------------------------------------------------------- /config/mysql/mysql.cnf: -------------------------------------------------------------------------------- 1 | # [client] 2 | # port = 3306 3 | # default-character-set = utf8mb4 4 | # 5 | # 6 | # [mysqld] 7 | # user = mysql 8 | # port = 3306 9 | # sql_mode = "" 10 | # 11 | # default-storage-engine = InnoDB 12 | # default-authentication-plugin = mysql_native_password 13 | # character-set-server = utf8mb4 14 | # collation-server = utf8mb4_unicode_ci 15 | # init_connect = 'SET NAMES utf8mb4' 16 | # 17 | # disable-log-bin 18 | # skip-character-set-client-handshake 19 | # explicit_defaults_for_timestamp 20 | # 21 | # slow_query_log 22 | # long_query_time = 3 23 | # slow-query-log-file = /var/lib/mysql/mysql.slow.log 24 | # log-error = /var/lib/mysql/mysql.error.log 25 | # # mysql 5.7 Please note the following 26 | # log-bin = /var/lib/mysql/logbin.log 27 | # # close log 28 | # skip-log-bin 29 | # default-time-zone = '+8:00' 30 | # # skip-grant-tables 31 | # 32 | # max_connections = 10000 33 | 34 | [mysql] 35 | default-character-set = utf8mb4 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Wallace Gao 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /config/nginx/conf.d/lua.conf: -------------------------------------------------------------------------------- 1 | 2 | # lua 配置 3 | lua_shared_dict limit 20m; 4 | # 设置防火墙包路径 5 | lua_package_path "/usr/local/openresty/nginx/conf/lua/waf/?.lua;;"; 6 | init_by_lua_file "/usr/local/openresty/nginx/conf/lua/waf/init.lua"; 7 | 8 | server { 9 | listen 80; 10 | server_name lua.localhost; 11 | # 开启防火墙 12 | access_by_lua_file conf/lua/waf/waf.lua; 13 | 14 | resolver 8.8.8.8 114.114.114.114 valid=3600s; 15 | location /http { 16 | default_type text/html; 17 | # lua_code_cache off; # 关闭缓存 18 | rewrite_by_lua_block { 19 | } 20 | header_filter_by_lua_block { 21 | ngx.header.content_type = "text/html;charset=utf8" 22 | } 23 | content_by_lua_file conf/lua/test/http.lua; 24 | } 25 | 26 | location / { 27 | default_type text/html; 28 | content_by_lua_block { 29 | ngx.say("

hello, world

") 30 | } 31 | } 32 | 33 | location /redis { 34 | default_type text/html; 35 | content_by_lua_file conf/lua/test/redis.lua; 36 | } 37 | 38 | location /mysql { 39 | default_type text/html; 40 | content_by_lua_file conf/lua/test/mysql.lua; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /config/yapi/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG NODE_IMAGES 2 | FROM ${NODE_IMAGES} 3 | 4 | ARG YAPI_VERSION 5 | ARG YAPI_HOME 6 | ARG YAPI_HOST_PORT 7 | 8 | ENV VENDORS ${YAPI_HOME}/vendors 9 | ENV GIT_URL https://github.com/YMFE/yapi.git 10 | ENV GIT_MIRROR_URL https://gitee.com/mirrors/YApi.git 11 | 12 | COPY ./wait-for-it.sh / 13 | COPY ./entrypoint.sh /bin 14 | 15 | WORKDIR ${YAPI_HOME}/ 16 | 17 | RUN echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.4/main/" > /etc/apk/repositories 18 | 19 | RUN apk update \ 20 | && apk upgrade \ 21 | && apk add --no-cache git curl python make openssl tar gcc bash \ 22 | && rm -rf /var/cache/apk/* 23 | 24 | RUN rm -rf node && \ 25 | ret=`curl -s https://api.ip.sb/geoip | grep China | wc -l` && \ 26 | if [ $ret -ne 0 ]; then \ 27 | GIT_URL=${GIT_MIRROR_URL} && npm config set registry https://registry.npm.taobao.org; \ 28 | fi; \ 29 | echo ${GIT_URL} && \ 30 | git clone --depth 1 ${GIT_URL} vendors && \ 31 | cd vendors && \ 32 | npm install -g node-gyp yapi-cli && \ 33 | npm install --production && \ 34 | chmod +x /bin/entrypoint.sh && \ 35 | chmod +x /wait-for-it.sh 36 | 37 | EXPOSE ${YAPI_HOST_PORT} 38 | ENTRYPOINT ["entrypoint.sh"] 39 | -------------------------------------------------------------------------------- /config/lua/test/http.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Author: seekwe 3 | Date: 2020-08-13 16:05:18 4 | Last Modified by:: seekwe 5 | Last Modified time: 2020-08-14 18:31:26 6 | --]] 7 | 8 | -- curl --request POST 'http://nginx:81/http?get=isGet' --form 'post=yesPost' 9 | 10 | local request_method = ngx.var.request_method 11 | 12 | local ua = ngx.var.http_user_agent 13 | 14 | local ip = getClientIp() 15 | 16 | ngx.say(os.date("%Y-%m-%d %H:%M:%S",os.time())," ",os.getenv("TZ")) 17 | ngx.say("
") 18 | ngx.say("IP: ",ip) 19 | ngx.say("method: ",request_method) 20 | ngx.say("
") 21 | ngx.say("user_agent: ",ua) 22 | ngx.say("
") 23 | 24 | if ngx.req.get_uri_args()["jump"] == nil then 25 | ngx.say('没有 Get 参数,手动设置一个') 26 | ngx.say("
") 27 | ngx.req.set_uri_args({help = 'yes'}); 28 | end 29 | 30 | if request_method == "POST" then 31 | ngx.req.read_body() -- 解析 body 参数之前一定要先读取 body 32 | local arg = ngx.req.get_post_args() 33 | for k,v in pairs(arg) do 34 | ngx.say("[POST] ", k, ": ", v,"
") 35 | end 36 | end 37 | 38 | local arg = ngx.req.get_uri_args() 39 | for k,v in pairs(arg) do 40 | ngx.say("[GET] ", k, ": ", v,"
") 41 | end 42 | 43 | for k,v in pairs(ngx.req.get_headers()) do 44 | ngx.say("[HEAD] ", k, ": ", v,"
") 45 | end 46 | 47 | ngx.exit(ngx.OK) -------------------------------------------------------------------------------- /config/lua/waf/config.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Author: seekwe 3 | Date: 2019-10-27 18:24:58 4 | Last Modified by:: seekwe 5 | Last Modified time: 2020-08-14 20:46:44 6 | --]] 7 | 8 | --规则存放目录 9 | RulePath = "wafconf/" 10 | --是否开启攻击信息记录,需要配置logdir 11 | Attacklog = "off" 12 | --log存储目录,该目录需要用户自己新建,切需要nginx用户的可写权限 13 | Logdir = "/var/log/nginx/" 14 | --是否拦截url访问 15 | UrlDeny="on" 16 | --是否拦截后重定向 17 | Redirect="on" 18 | --是否拦截cookie攻击 19 | CookieMatch="on" 20 | --是否拦截post攻击 21 | PostMatch="off" 22 | --是否开启URL白名单 23 | WhiteModule="off" 24 | --是否开启主机(对应nginx里面的server_name)白名单 25 | WhiteHostModule="off" 26 | --不可可上传文件后缀类型 27 | BlackFileExt={"php","jsp"} 28 | --ip白名单,多个ip用逗号分隔 29 | IpWhitelist={"127.0.0.1","172.16.1.0-172.16.1.255"} 30 | --ip黑名单,多个ip用逗号分隔 31 | IpBlocklist={"1.0.0.1","2.0.0.0-2.0.0.255"} 32 | --server_name白名单,多个用逗号分隔 33 | HostWhiteList = {"blog.73zls.com"} 34 | --是否开启拦截cc攻击(需要nginx.conf的http段增加lua_shared_dict limit 10m;) 35 | CCDeny="on" 36 | --设置cc攻击频率,单位为秒.默认1分钟同一个IP只能请求同一个地址70次 37 | CCrate="70/60" 38 | Html=[[ 39 | 40 | 41 | 42 | 43 |

503 Service Temporarily Unavailable

44 |
nginx
45 | 46 | 47 | ]] 48 | 49 | -------------------------------------------------------------------------------- /config/php/php-fpm.conf: -------------------------------------------------------------------------------- 1 | ;;;;;;;;;;;;;;;;;;;;; 2 | ; FPM Configuration ; 3 | ;;;;;;;;;;;;;;;;;;;;; 4 | 5 | ;;;;;;;;;;;;;;;;;; 6 | ; Global Options ; 7 | ;;;;;;;;;;;;;;;;;; 8 | 9 | [global] 10 | pid = /var/run/php-fpm.pid 11 | error_log = /var/log/php/php-fpm.log 12 | log_level = warning 13 | 14 | emergency_restart_threshold = 30 15 | emergency_restart_interval = 60s 16 | process_control_timeout = 5s 17 | daemonize = yes 18 | 19 | ;;;;;;;;;;;;;;;;;;;; 20 | ; Pool Definitions ; 21 | ;;;;;;;;;;;;;;;;;;;; 22 | 23 | [www] 24 | ;listen = /dev/shm/php-cgi.sock 25 | listen = 127.0.0.1:9000 26 | ;listen.backlog = -1 27 | ;listen.allowed_clients = 127.0.0.1 28 | ;listen.owner = www-data 29 | ;listen.group = www-data 30 | ;listen.mode = 0666 31 | user = www-data 32 | group = www-data 33 | 34 | pm = dynamic 35 | pm.max_children = 100 36 | pm.start_servers = 10 37 | pm.min_spare_servers = 10 38 | pm.max_spare_servers = 40 39 | ;pm.max_requests = 2048 40 | pm.process_idle_timeout = 10s 41 | request_terminate_timeout = 120 42 | request_slowlog_timeout = 0 43 | 44 | ;pm.status_path = /php-fpm_status 45 | slowlog = /var/log/php/slow.log 46 | rlimit_files = 51200 47 | rlimit_core = 0 48 | 49 | catch_workers_output = yes 50 | ;env[HOSTNAME] = ubuntu 51 | env[PATH] = /usr/local/bin:/usr/bin:/bin 52 | env[TMP] = /tmp 53 | env[TMPDIR] = /tmp 54 | env[TEMP] = /tmp 55 | -------------------------------------------------------------------------------- /config/lua/test/redis.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Author: seekwe 3 | Date: 2020-08-13 17:45:02 4 | Last Modified by:: seekwe 5 | Last Modified time: 2020-08-13 18:24:22 6 | --]] 7 | 8 | -- curl 'http://nginx:81/redis' 9 | 10 | -- redis config 11 | local redis = require "resty.redis" 12 | local red = redis:new() 13 | local redis_passwd = "73zls666" 14 | local redis_host = "172.0.0.40" 15 | 16 | local ok, err = red:connect(redis_host, 6379) 17 | 18 | if not ok then 19 | ngx.say("failed to connect: ", err) 20 | return 21 | end 22 | 23 | if redis_passwd then 24 | local count 25 | count, err = red:get_reused_times() 26 | if 0 == count then 27 | ok, err = red:auth(redis_passwd) 28 | if not ok then 29 | ngx.say("failed to auth: ", err) 30 | return 31 | end 32 | elseif err then 33 | ngx.say("failed to get reused times: ", err) 34 | return 35 | end 36 | end 37 | 38 | ok, err = red:set("dog", "an animal1") 39 | if not ok then 40 | ngx.say("failed to set dog: ", err) 41 | return 42 | end 43 | 44 | ngx.say("set result: ", ok) 45 | 46 | local res, err = red:get("dog") 47 | if not res then 48 | ngx.say("failed to get dog: ", err) 49 | return 50 | end 51 | 52 | if res == ngx.null then 53 | ngx.say("dog not found.") 54 | return 55 | end 56 | 57 | ngx.say("dog: ", res) 58 | 59 | -------------------------------------------------------------------------------- /config/lua/test/mysql.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Author: seekwe 3 | Date: 2020-08-13 18:20:29 4 | Last Modified by:: seekwe 5 | Last Modified time: 2020-08-13 18:24:12 6 | --]] 7 | 8 | -- curl 'http://nginx:81/mysql' 9 | 10 | local cjson = require "cjson" 11 | local mysql = require "resty.mysql" 12 | 13 | local db = mysql:new() 14 | local ok, err, errcode, sqlstate = db:connect({ 15 | host = "172.0.0.20", 16 | port = 3306, 17 | database = "mysql", 18 | user = "root", 19 | password = "73zls666"}) 20 | 21 | if not ok then 22 | ngx.log(ngx.ERR, "failed to connect: ", err, ": ", errcode, " ", sqlstate) 23 | return ngx.exit(500) 24 | end 25 | 26 | res, err, errcode, sqlstate = db:query("select 1; select 2; select 3;") 27 | if not res then 28 | ngx.log(ngx.ERR, "bad result #1: ", err, ": ", errcode, ": ", sqlstate, ".") 29 | return ngx.exit(500) 30 | end 31 | 32 | ngx.say("result #1: ", cjson.encode(res)) 33 | 34 | local i = 2 35 | while err == "again" do 36 | res, err, errcode, sqlstate = db:read_result() 37 | if not res then 38 | ngx.log(ngx.ERR, "bad result #", i, ": ", err, ": ", errcode, ": ", sqlstate, ".") 39 | return ngx.exit(500) 40 | end 41 | ngx.say("result #", i, ": ", cjson.encode(res)) 42 | i = i + 1 43 | end 44 | 45 | local ok, err = db:set_keepalive(10000, 50) 46 | if not ok then 47 | ngx.log(ngx.ERR, "failed to set keepalive: ", err) 48 | ngx.exit(500) 49 | end -------------------------------------------------------------------------------- /config/nginx/conf.d/localhost.conf: -------------------------------------------------------------------------------- 1 | server { 2 | # 使用是需要去掉默认站点设置`default_server` 3 | listen 80 default_server; 4 | charset utf-8; 5 | server_name localhost; 6 | root /var/www/html/localhost; 7 | index index.php index.html index.htm; 8 | 9 | # 开启防火墙 10 | access_by_lua_file conf/lua/waf/waf.lua; 11 | 12 | # jump https 13 | #rewrite ^(.*)$ https://$host$1 permanent; 14 | 15 | #error_page 404 /404.html; 16 | 17 | location ~ /.well-known { 18 | allow all; 19 | } 20 | 21 | # jump https 22 | #location ~ /.well-known { 23 | # rewrite ^(.*)$ https://$host$1 permanent; 24 | #} 25 | 26 | # rewrite 27 | location / { 28 | try_files $uri $uri/ /index.php$is_args$query_string; 29 | } 30 | 31 | location ~ \.php$ { 32 | fastcgi_pass php:9000; 33 | fastcgi_index index.php; 34 | include fastcgi_params; 35 | fastcgi_param PATH_INFO $fastcgi_path_info; 36 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 37 | } 38 | 39 | #location / { 40 | # proxy_pass http://172.0.0.1; # or http://host.docker.internal; 41 | # proxy_redirect off; 42 | # proxy_set_header Host $host; 43 | # proxy_set_header X-Real-IP $remote_addr; 44 | # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 45 | # proxy_set_header X-Forwarded-Proto $scheme; 46 | #} 47 | 48 | #location /php-fpm_status { 49 | # include fastcgi_params; 50 | # fastcgi_pass php:9000; 51 | # fastcgi_param SCRIPT_FILENAME $fastcgi_script_name; 52 | #} 53 | 54 | #access_log /var/log/nginx/nginx.localhost.access.log main; 55 | #error_log /var/log/nginx/nginx.localhost.error.log error; 56 | } 57 | 58 | -------------------------------------------------------------------------------- /docker.md: -------------------------------------------------------------------------------- 1 | # docker 安装文档 2 | 3 | ## CentOS 4 | 5 | 请按顺序执行以下命令 6 | 7 | ```bash 8 | # 安装依赖 9 | sudo yum install -y yum-utils device-mapper-persistent-data lvm2 10 | 11 | # 配置 repositories 12 | sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 13 | 14 | # 安装 docker 15 | sudo yum install docker-ce -y 16 | 17 | # 检查 dokcer 是否安装成功 18 | docker version 19 | 20 | # 启动 docker 21 | systemctl start docker 22 | 23 | # 开机自动启动 docker 24 | systemctl enable docker 25 | 26 | # 安装 docker-compose 27 | 28 | ## 如果安装失败可以使用 py 的 pip 安装,方式自行谷歌 29 | curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose 30 | ## 国内建议使用国内源 31 | curl -L "https://get.daocloud.io/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose 32 | 33 | 34 | ## 设置 docker-compose 权限 35 | chmod +x /usr/local/bin/docker-compose 36 | 37 | # 检查 docker-compose 是否安装成功 38 | docker-compose --version 39 | ``` 40 | 41 | ## Ubuntu 42 | 43 | ```bash 44 | sudo curl -sSL https://get.docker.com | sh 45 | sudo usermod pi -aG docker 46 | curl -L "https://get.daocloud.io/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose 47 | chmod +x /usr/local/bin/docker-compose 48 | ``` 49 | 50 | ## 更多问题 51 | 52 | **权限问题** 53 | 54 | 如果不是 root 用户或提示权限问题,可将当前用户加入 docker 用户组 55 | 56 | ```bash 57 | sudo groupadd docker 58 | sudo gpasswd -a ${USER} docker 59 | sudo service docker restart 60 | ``` 61 | 62 | **Pull 太慢** 63 | 64 | 如果是国内服务器请尝试更换 docker 源为国内源 65 | 66 | ```bash 67 | vi /etc/docker/daemon.json 68 | 69 | # {"registry-mirrors": ["https://registry.docker-cn.com"]} 70 | 71 | # 腾讯云 72 | # {"registry-mirrors": ["https://mirror.ccs.tencentyun.com"]} 73 | 74 | # 编辑后重启 dokcer 75 | systemctl daemon-reload 76 | systemctl restart docker 77 | ``` 78 | -------------------------------------------------------------------------------- /config/nginx/conf.d/localhost_https.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 443 ssl http2; 3 | server_name localhost; 4 | root /var/www/html/localhost; 5 | index index.php index.html index.htm; 6 | 7 | # 开启防火墙 8 | access_by_lua_file conf/lua/waf/waf.lua; 9 | 10 | access_log /dev/null; 11 | #access_log /var/log/nginx/nginx.localhost.https.access.log main; 12 | 13 | #error_log /var/log/nginx/nginx.localhost.https.error.log warn; 14 | 15 | # Please create your own certificate settings 16 | #ssl_certificate /etc/nginx/letsencrypt/localhost/fullchain1.pem; 17 | #ssl_certificate_key /etc/nginx/letsencrypt/localhost/privkey1.pem; 18 | ssl_certificate /etc/nginx/conf.d/certs/localhost/server.crt; 19 | ssl_certificate_key /etc/nginx/conf.d/certs/localhost/server.key; 20 | ssl_prefer_server_ciphers on; 21 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 22 | ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4"; 23 | add_header Strict-Transport-Security max-age=31536000; 24 | 25 | #error_page 404 /404.html; 26 | 27 | # redirect server error pages to the static page /50x.html 28 | error_page 500 502 503 504 /50x.html; 29 | location = /50x.html { 30 | root /usr/share/nginx/html; 31 | } 32 | 33 | location ~ /.well-known { 34 | allow all; 35 | } 36 | 37 | # proxy the swoole, You need to comment out the following rewrite 38 | # location / { 39 | # proxy_set_header Host $http_host; 40 | # proxy_set_header X-Real-IP $remote_addr; 41 | # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 42 | # proxy_set_header X-Forwarded-Proto $scheme; 43 | # proxy_pass https://172.0.0.30:8081; 44 | # } 45 | 46 | # rewrite 47 | location / { 48 | try_files $uri $uri/ /index.php$is_args$query_string; 49 | } 50 | 51 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 52 | location ~ \.php$ { 53 | fastcgi_pass php:9000; 54 | fastcgi_index index.php; 55 | include fastcgi_params; 56 | fastcgi_param PATH_INFO $fastcgi_path_info; 57 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /www/localhost/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 程序版本信息 8 | 9 | 10 | 11 | 数据库管理'; 13 | echo '

程序版本信息

'; 14 | echo ''; 21 | 22 | echo '

已安装的php扩展

'; 23 | printExtensions(); 24 | 25 | /** 26 | * 获取MySQL版本 27 | */ 28 | function getMysqlVersion() 29 | { 30 | if (extension_loaded('PDO_MYSQL')) { 31 | try { 32 | $dbh = new PDO('mysql:host=mysql;dbname=mysql', 'root', $_SERVER['MYSQL_ROOT_PASSWORD']??''); 33 | $sth = $dbh->query('SELECT VERSION() as version'); 34 | $info = $sth->fetch(); 35 | } catch (PDOException $e) { 36 | if(strpos($e->getMessage(), 'getaddrinfo failed: Name ')){ 37 | return "Mysql 没有启动"; 38 | } 39 | return $e->getMessage(); 40 | } 41 | return $info['version']; 42 | } else { 43 | return 'PDO_MYSQL 扩展未安装 ×'; 44 | } 45 | 46 | } 47 | 48 | /** 49 | * 获取Redis版本 50 | */ 51 | function getRedisVersion() 52 | { 53 | if (extension_loaded('redis')) { 54 | try { 55 | $redis = new Redis(); 56 | $redis->connect('redis', 6379); 57 | $redis->auth($_SERVER['REDIS_PASSWORD'] ?? ''); 58 | /** @var array $info */ 59 | $info = $redis->info(); 60 | return $info['redis_version']; 61 | } catch (Exception $e) { 62 | if(strpos($e->getMessage(), 'Name does not resolve')){ 63 | return "Redis 没有启动"; 64 | } 65 | return $e->getMessage(); 66 | } 67 | } else { 68 | return 'Redis 扩展未安装 ×'; 69 | } 70 | } 71 | 72 | /** 73 | * 获取已安装扩展列表 74 | */ 75 | function printExtensions() 76 | { 77 | echo '
    '; 78 | foreach (get_loaded_extensions() as $i => $name) { 79 | echo "
  1. ", $name, '=', phpversion($name), '
  2. '; 80 | } 81 | echo '
'; 82 | } 83 | ?> 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /config/lua/waf/waf.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Author: seekwe 3 | Date: 2019-10-27 18:24:58 4 | Last Modified by:: seekwe 5 | Last Modified time: 2020-08-13 19:06:24 6 | --]] 7 | 8 | local content_length=tonumber(ngx.req.get_headers()['content-length']) 9 | local method=ngx.req.get_method() 10 | local ngxmatch=ngx.re.match 11 | if whiteip() then 12 | elseif whitehost() then 13 | elseif whiteua() then 14 | elseif blockip() then 15 | elseif denycc() then 16 | elseif ngx.var.http_Acunetix_Aspect then 17 | ngx.exit(444) 18 | elseif ngx.var.http_X_Scan_Memo then 19 | ngx.exit(444) 20 | elseif whiteurl() then 21 | elseif ua() then 22 | elseif url() then 23 | elseif args() then 24 | elseif cookie() then 25 | elseif PostCheck then 26 | if method=="POST" then 27 | local boundary = get_boundary() 28 | if boundary then 29 | local len = string.len 30 | local sock, err = ngx.req.socket() 31 | if not sock then 32 | return 33 | end 34 | ngx.req.init_body(128 * 1024) 35 | sock:settimeout(0) 36 | local content_length = nil 37 | content_length=tonumber(ngx.req.get_headers()['content-length']) 38 | local chunk_size = 4096 39 | if content_length < chunk_size then 40 | chunk_size = content_length 41 | end 42 | local size = 0 43 | while size < content_length do 44 | local data, err, partial = sock:receive(chunk_size) 45 | data = data or partial 46 | if not data then 47 | return 48 | end 49 | ngx.req.append_body(data) 50 | if body(data) then 51 | return true 52 | end 53 | size = size + len(data) 54 | local m = ngxmatch(data,[[Content-Disposition: form-data;(.+)filename="(.+)\\.(.*)"]],'ijo') 55 | if m then 56 | fileExtCheck(m[3]) 57 | filetranslate = true 58 | else 59 | if ngxmatch(data,"Content-Disposition:",'isjo') then 60 | filetranslate = false 61 | end 62 | if filetranslate==false then 63 | if body(data) then 64 | return true 65 | end 66 | end 67 | end 68 | local less = content_length - size 69 | if less < chunk_size then 70 | chunk_size = less 71 | end 72 | end 73 | ngx.req.finish_body() 74 | else 75 | ngx.req.read_body() 76 | local args = ngx.req.get_post_args() 77 | if not args then 78 | return 79 | end 80 | for key, val in pairs(args) do 81 | if type(val) == "table" then 82 | if type(val[1]) == "boolean" then 83 | return 84 | end 85 | data=table.concat(val, ", ") 86 | else 87 | data=val 88 | end 89 | if data and type(data) ~= "boolean" and body(data) then 90 | return true 91 | end 92 | end 93 | end 94 | end 95 | else 96 | return 97 | end 98 | -------------------------------------------------------------------------------- /config/php/extensions/php.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo 4 | echo "============================================" 5 | echo "Install extensions from : ${MORE_EXTENSION_INSTALLER}" 6 | echo "Extra Extensions : ${PHP_EXTENSIONS}" 7 | echo "Multicore Compilation : ${MC}" 8 | echo "Work directory : ${PWD}" 9 | echo "============================================" 10 | echo 11 | 12 | 13 | if [ -z "${EXTENSIONS##*,mcrypt,*}" ]; then 14 | echo "---------- mcrypt was REMOVED from PHP 7.2.0 ----------" 15 | fi 16 | 17 | 18 | if [ -z "${EXTENSIONS##*,mysql,*}" ]; then 19 | echo "---------- mysql was REMOVED from PHP 7.0.0 ----------" 20 | fi 21 | 22 | 23 | if [ -z "${EXTENSIONS##*,sodium,*}" ]; then 24 | echo "---------- Install sodium ----------" 25 | echo "Sodium is bundled with PHP from PHP 7.2.0 " 26 | fi 27 | 28 | if [ -z "${EXTENSIONS##*,swoole,*}" ]; then 29 | echo "---------- Install swoole ----------" 30 | # git clone --depth=1 31 | cd /tmp/extensions 32 | curl -o ./swoole.tar.gz https://github.com/swoole/swoole-src/archive/master.tar.gz -L && \ 33 | tar zxvf ./swoole.tar.gz && \ 34 | mv swoole-src* swoole-src && \ 35 | cd swoole-src && \ 36 | phpize && \ 37 | ./configure \ 38 | --enable-openssl \ 39 | --enable-http2 && \ 40 | make clean && make && make install 41 | # pecl install swoole \ 42 | docker-php-ext-enable swoole 43 | fi 44 | 45 | # if [ -z "${EXTENSIONS##*,swoole_tracker,*}" ]; then 46 | # echo "---------- Install swoole_tracker ----------" 47 | # cd /tmp/extensions 48 | # chmod +x ./swoole-tracker-install.sh && \ 49 | # ./swoole-tracker-install.sh && \ 50 | # rm ./swoole-tracker-install.sh 51 | # echo -e "\033[32m echo -e 'extension=/usr/local/etc/php/swoole-tracker/swoole_tracker73.so\napm.enable=1\napm.sampling_rate=100' > /usr/local/etc/php/conf.d/swoole-tracker.ini \033[0m" 52 | # cp -r swoole-tracker /usr/local/etc/php/ 53 | # fi 54 | 55 | if [ -z "${EXTENSIONS##*,mongodb,*}" ]; then 56 | echo "---------- Install mongodb ----------" 57 | pecl install mongodb 58 | docker-php-ext-enable mongodb 59 | fi 60 | 61 | if [ -z "${EXTENSIONS##*,yaf,*}" ]; then 62 | echo "---------- Install yaf ----------" 63 | pecl install yaf 64 | docker-php-ext-enable yaf 65 | fi 66 | 67 | if [ -z "${EXTENSIONS##*,amqp,*}" ]; then 68 | echo "---------- Install amqp ----------" 69 | apk add --no-cache rabbitmq-c-dev 70 | cd /tmp/extensions 71 | pecl install amqp-1.9.4.tgz 72 | docker-php-ext-enable amqp 73 | fi 74 | 75 | if [ -z "${EXTENSIONS##*,redis,*}" ]; then 76 | echo "---------- Install redis ----------" 77 | mkdir redis \ 78 | && tar -xf redis-4.3.0.tgz -C redis --strip-components=1 \ 79 | && ( cd redis && phpize && ./configure && make ${MC} && make install ) \ 80 | && docker-php-ext-enable redis 81 | fi 82 | 83 | if [ -z "${EXTENSIONS##*,memcached,*}" ]; then 84 | echo "---------- Install memcached ----------" 85 | apk add --no-cache libmemcached-dev zlib-dev 86 | printf "\n" | pecl install memcached-3.1.3 87 | docker-php-ext-enable memcached 88 | fi 89 | 90 | if [ -z "${EXTENSIONS##*,xdebug,*}" ]; then 91 | echo "---------- Install xdebug ----------" 92 | cd /tmp/extensions 93 | tar -xf xdebug-2.6.1.tgz -C xdebug --strip-components=1 \ 94 | && ( cd xdebug && phpize && ./configure && make ${MC} && make install ) \ 95 | && docker-php-ext-enable xdebug 96 | fi 97 | 98 | if [ -z "${EXTENSIONS##*,pdo_sqlsrv,*}" ]; then 99 | echo "---------- Install pdo_sqlsrv ----------" 100 | apk add --no-cache unixodbc-dev 101 | pecl install pdo_sqlsrv 102 | docker-php-ext-enable pdo_sqlsrv 103 | fi 104 | 105 | if [ -z "${EXTENSIONS##*,sqlsrv,*}" ]; then 106 | echo "---------- Install sqlsrv ----------" 107 | apk add --no-cache unixodbc-dev 108 | printf "\n" | pecl install sqlsrv 109 | docker-php-ext-enable sqlsrv 110 | fi 111 | -------------------------------------------------------------------------------- /config/nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | # nginx.conf -- docker-openresty 2 | # 3 | # This file is installed to: 4 | # `/usr/local/openresty/nginx/conf/nginx.conf` 5 | # and is the file loaded by nginx at startup, 6 | # unless the user specifies otherwise. 7 | # 8 | # It tracks the upstream OpenResty's `nginx.conf`, but removes the `server` 9 | # section and adds this directive: 10 | # `include /etc/nginx/conf.d/*.conf;` 11 | # 12 | # The `docker-openresty` file `nginx.vh.default.conf` is copied to 13 | # `/etc/nginx/conf.d/default.conf`. It contains the `server section 14 | # of the upstream `nginx.conf`. 15 | # 16 | # See https://github.com/openresty/docker-openresty/blob/master/README.md#nginx-config-files 17 | # 18 | 19 | #user nobody; 20 | #worker_processes 1; 21 | 22 | # Enables the use of JIT for regular expressions to speed-up their processing. 23 | pcre_jit on; 24 | 25 | 26 | 27 | #error_log logs/error.log; 28 | #error_log logs/error.log notice; 29 | #error_log logs/error.log info; 30 | 31 | #pid logs/nginx.pid; 32 | 33 | 34 | events { 35 | worker_connections 1024; 36 | } 37 | 38 | 39 | http { 40 | include mime.types; 41 | default_type application/octet-stream; 42 | 43 | # Enables or disables the use of underscores in client request header fields. 44 | # When the use of underscores is disabled, request header fields whose names contain underscores are marked as invalid and become subject to the ignore_invalid_headers directive. 45 | # underscores_in_headers off; 46 | 47 | #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 48 | # '$status $body_bytes_sent "$http_referer" ' 49 | # '"$http_user_agent" "$http_x_forwarded_for"'; 50 | 51 | #access_log logs/access.log main; 52 | 53 | # Log in JSON Format 54 | # log_format nginxlog_json escape=json '{ "timestamp": "$time_iso8601", ' 55 | # '"remote_addr": "$remote_addr", ' 56 | # '"body_bytes_sent": $body_bytes_sent, ' 57 | # '"request_time": $request_time, ' 58 | # '"response_status": $status, ' 59 | # '"request": "$request", ' 60 | # '"request_method": "$request_method", ' 61 | # '"host": "$host",' 62 | # '"upstream_addr": "$upstream_addr",' 63 | # '"http_x_forwarded_for": "$http_x_forwarded_for",' 64 | # '"http_referrer": "$http_referer", ' 65 | # '"http_user_agent": "$http_user_agent", ' 66 | # '"http_version": "$server_protocol", ' 67 | # '"nginx_access": true }'; 68 | # access_log /dev/stdout nginxlog_json; 69 | 70 | # See Move default writable paths to a dedicated directory (#119) 71 | # https://github.com/openresty/docker-openresty/issues/119 72 | client_body_temp_path /var/run/openresty/nginx-client-body; 73 | proxy_temp_path /var/run/openresty/nginx-proxy; 74 | fastcgi_temp_path /var/run/openresty/nginx-fastcgi; 75 | uwsgi_temp_path /var/run/openresty/nginx-uwsgi; 76 | scgi_temp_path /var/run/openresty/nginx-scgi; 77 | 78 | sendfile on; 79 | #tcp_nopush on; 80 | 81 | #keepalive_timeout 0; 82 | keepalive_timeout 65; 83 | 84 | client_max_body_size 20m; 85 | 86 | #Gzip Compression 87 | gzip on; 88 | gzip_buffers 16 8k; 89 | gzip_comp_level 6; 90 | gzip_http_version 1.1; 91 | gzip_min_length 256; 92 | gzip_proxied any; 93 | gzip_vary on; 94 | gzip_types 95 | text/xml application/xml application/atom+xml application/rss+xml application/xhtml+xml image/svg+xml 96 | text/javascript application/javascript application/x-javascript 97 | text/x-json application/json application/x-web-app-manifest+json 98 | text/css text/plain text/x-component 99 | font/opentype application/x-font-ttf application/vnd.ms-fontobject 100 | image/x-icon; 101 | gzip_disable "MSIE [1-6]\.(?!.*SV1)"; 102 | 103 | include /etc/nginx/conf.d/*.conf; 104 | 105 | # Don't reveal OpenResty version to clients. 106 | # server_tokens off; 107 | } -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | ### environment config file ############################### 2 | SOURCE_DIR=./www 3 | 4 | ### Ubuntu ################################################# 5 | UBUNTU_IMAGES=seekwe/ubuntu18:v2 6 | 7 | ### Nginx ################################################## 8 | # 更多版本选择:https://hub.docker.com/r/openresty/openresty/tags 9 | NGINX_IMAGES=openresty/openresty:1.21.4.1-2-bionic 10 | NGINX_HTTP_HOST_PORT=80 11 | NGINX_HTTPS_HOST_PORT=443 12 | NGINX_CONFD_DIR=./config/nginx/conf.d 13 | NGINX_CONF_FILE=./config/nginx/nginx.conf 14 | NGINX_LOG_DIR=./logs/nginx 15 | LUA_DIR=./config/lua 16 | 17 | ### Caddy ################################################### 18 | # 更多版本选择:https://hub.docker.com/_/caddy?tab=tags 19 | CADDY_IMAGES=caddy:2.6.2 20 | CADDY_CONF_DIR=./config/caddy 21 | CADDY_SSL_DIR=./data/caddy 22 | CADDY_LOG_DIR=./logs/caddy 23 | CADDY_HTTP_HOST_PORT=80 24 | CADDY_HTTPS_HOST_PORT=443 25 | 26 | ### PHP ##################################################### 27 | # 更多版本选择:https://hub.docker.com/_/php/?tab=tags 28 | PHP_IMAGES=php:7.4.9-fpm-alpine 29 | # PHP 安装源 阿里云:mirrors.aliyun.com 清华:mirrors.tuna.tsinghua.edu.cn 30 | ALPINE_REPOSITORIES=mirrors.tuna.tsinghua.edu.cn 31 | PHP_PHP_CONF_FILE=./config/php/php.ini 32 | PHP_FPM_CONF_FILE=./config/php/php-fpm.conf 33 | PHP_LOG_DIR=./logs/php 34 | # 可用扩展: 35 | # pdo_mysql,odbc,pcntl,mysqli,mbstring,exif,bcmath,calendar, 36 | # sockets,gettext,shmop,sysvmsg,sysvsem,sysvshm,pdo_rebird, 37 | # pdo_dblib,pdo_oci,pdo_odbc,pdo_pgsql,pgsql,oci8,dba,gmp,zip, 38 | # gd,intl,bz2,soap,xsl,xmlrpc,wddx,curl,readline,snmp,pspell, 39 | # recode,tidy,imap,ldap,imagick,sqlsrv,mcrypt,opcache,mongodb, 40 | # redis,memcached,xdebug,swoole,pdo_sqlsrv,sodium,yaf,mysql, 41 | # 如果使用多个主题,请用逗号(,)分隔,注意前后都有(,) 42 | PHP_EXTENSIONS=,pdo_mysql,mysqli,gd,opcache,redis,zip,pcntl,exif,bcmath,sockets,gettext,intl,xmlrpc,mcrypt, 43 | 44 | ### MySQL ################################################### 45 | # 更多版本选择:https://hub.docker.com/_/mariadb/?tab=tags 46 | MYSQL_IMAGES=mariadb:10.9.4 47 | # 安全:不将端口暴露到外部网络 48 | MYSQL_HOST_PORT=127.0.0.1:3306 49 | MYSQL_ROOT_PASSWORD=73zls666 50 | MYSQL_DATABASE=zls 51 | MYSQL_DATA_DIR=./data/mysql 52 | MYSQL_CONF_DIR=./config/mysql 53 | MYSQL_CONF_FILE=./config/mysql/mysql.cnf 54 | 55 | ### Redis #################################################### 56 | REDIS_IMAGES=redis:5.0.9-alpine 57 | # 安全:不将端口暴露到外部网络 58 | REDIS_HOST_PORT=127.0.0.1:6379 59 | REDIS_CONF_FILE=./config/redis/redis.conf 60 | REDIS_PASSWORD=73zls666 61 | 62 | 63 | ### MONGODB ################################################## 64 | MONGODB_IMAGES=mongo:5.0.8 65 | MONGODB_CONF_DIR=./config/mongodb 66 | MONGODB_DATA_DIR=./data/mongo 67 | # 安全:不将端口暴露到外部网络 68 | MONGODB_HOST_PORT=127.0.0.1:27017 69 | MONGODB_INITDB_ROOT_USERNAME=root 70 | MONGODB_INITDB_ROOT_PASSWORD=73zls666 71 | 72 | ### COMPOSER ################################################# 73 | COMPOSER_DATA_DIR=./data/composer 74 | COMPOSER_VERSION=1.8.6 75 | COMPOSER_PACKAGIST=https://mirrors.aliyun.com/composer/ 76 | 77 | ### POSTGRES ################################################# 78 | POSTGRES_IMAGES=postgres:15.0 79 | POSTGRES_DATA_DIR=./data/postgres 80 | # 安全:不将端口暴露到外部网络 81 | POSTGRES_PORT=127.0.0.1:5432 82 | POSTGRES_DB=zls 83 | POSTGRES_USER=root 84 | POSTGRES_PASSWORD=73zls666 85 | 86 | ### SENTRY ################################################# 87 | SENTRY_IMAGES=sentry:latest 88 | SENTRY_DATA_DIR=./data/secret 89 | SENTRY_PORT=9000 90 | SENTRY_SECRET_KEY=")=uv7e1glkx9j&&wfesa5ffmz9atu3wh&1xe(mm(yemgbq-1#(" 91 | 92 | ### PORTAINER ############################################## 93 | PORTAINER_IMAGES=portainer/portainer 94 | PORTAINER_DATA_DIR=./data/portainer 95 | PORTAINER_HOST_PORT=9001 96 | 97 | ### YAPI ################################################### 98 | YAPI_VERSION=1.8.1 99 | YAPI_HOST_PORT=3000 100 | YAPI_CONFIG_FILE=./config/yapi/config.json 101 | YAPI_HOME=/home 102 | YAPI_LOG_DIR=./logs/yapi 103 | 104 | ### MONITOR ################################################ 105 | # https://grafana.com/grafana/dashboards 106 | GRAFANA_IMAGES=grafana/grafana:7.3.6 107 | GRAFANA_PORT=3000 108 | GRAFANA_PASSWORD=admin666 109 | GRAFANA_CONFIG_FILE=./config/grafana/grafana.ini 110 | GRAFANA_DATA_DIR=./data/grafana 111 | GRAFANA_LOG_DIR=./logs/grafana 112 | 113 | PROM_IMAGES=prom/prometheus:v2.23.0 114 | PROM_PORT=127.0.0.1:3001 115 | PROM_CONFIG_FILE=./config/grafana/prometheus.yml 116 | PROM_DATA_DIR=./data/prometheus 117 | 118 | ### Golang ################################################# 119 | GO_IMAGES=golang:latest 120 | 121 | ### node ################################################### 122 | NODE_IMAGES=node:10.16.0-alpine 123 | -------------------------------------------------------------------------------- /config/yapi/wait-for-it.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Use this script to test if a given TCP host/port are available 3 | 4 | WAITFORIT_cmdname=${0##*/} 5 | 6 | echoerr() { if [[ $WAITFORIT_QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } 7 | 8 | usage() 9 | { 10 | cat << USAGE >&2 11 | Usage: 12 | $WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args] 13 | -h HOST | --host=HOST Host or IP under test 14 | -p PORT | --port=PORT TCP port under test 15 | Alternatively, you specify the host and port as host:port 16 | -s | --strict Only execute subcommand if the test succeeds 17 | -q | --quiet Don't output any status messages 18 | -t TIMEOUT | --timeout=TIMEOUT 19 | Timeout in seconds, zero for no timeout 20 | -- COMMAND ARGS Execute command with args after the test finishes 21 | USAGE 22 | exit 1 23 | } 24 | 25 | wait_for() 26 | { 27 | if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then 28 | echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT" 29 | else 30 | echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout" 31 | fi 32 | WAITFORIT_start_ts=$(date +%s) 33 | while : 34 | do 35 | if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then 36 | nc -z $WAITFORIT_HOST $WAITFORIT_PORT 37 | WAITFORIT_result=$? 38 | else 39 | (echo > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1 40 | WAITFORIT_result=$? 41 | fi 42 | if [[ $WAITFORIT_result -eq 0 ]]; then 43 | WAITFORIT_end_ts=$(date +%s) 44 | echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds" 45 | break 46 | fi 47 | sleep 1 48 | done 49 | return $WAITFORIT_result 50 | } 51 | 52 | wait_for_wrapper() 53 | { 54 | # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 55 | if [[ $WAITFORIT_QUIET -eq 1 ]]; then 56 | timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT & 57 | else 58 | timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT & 59 | fi 60 | WAITFORIT_PID=$! 61 | trap "kill -INT -$WAITFORIT_PID" INT 62 | wait $WAITFORIT_PID 63 | WAITFORIT_RESULT=$? 64 | if [[ $WAITFORIT_RESULT -ne 0 ]]; then 65 | echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT" 66 | fi 67 | return $WAITFORIT_RESULT 68 | } 69 | 70 | # process arguments 71 | while [[ $# -gt 0 ]] 72 | do 73 | case "$1" in 74 | *:* ) 75 | WAITFORIT_hostport=(${1//:/ }) 76 | WAITFORIT_HOST=${WAITFORIT_hostport[0]} 77 | WAITFORIT_PORT=${WAITFORIT_hostport[1]} 78 | shift 1 79 | ;; 80 | --child) 81 | WAITFORIT_CHILD=1 82 | shift 1 83 | ;; 84 | -q | --quiet) 85 | WAITFORIT_QUIET=1 86 | shift 1 87 | ;; 88 | -s | --strict) 89 | WAITFORIT_STRICT=1 90 | shift 1 91 | ;; 92 | -h) 93 | WAITFORIT_HOST="$2" 94 | if [[ $WAITFORIT_HOST == "" ]]; then break; fi 95 | shift 2 96 | ;; 97 | --host=*) 98 | WAITFORIT_HOST="${1#*=}" 99 | shift 1 100 | ;; 101 | -p) 102 | WAITFORIT_PORT="$2" 103 | if [[ $WAITFORIT_PORT == "" ]]; then break; fi 104 | shift 2 105 | ;; 106 | --port=*) 107 | WAITFORIT_PORT="${1#*=}" 108 | shift 1 109 | ;; 110 | -t) 111 | WAITFORIT_TIMEOUT="$2" 112 | if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fi 113 | shift 2 114 | ;; 115 | --timeout=*) 116 | WAITFORIT_TIMEOUT="${1#*=}" 117 | shift 1 118 | ;; 119 | --) 120 | shift 121 | WAITFORIT_CLI=("$@") 122 | break 123 | ;; 124 | --help) 125 | usage 126 | ;; 127 | *) 128 | echoerr "Unknown argument: $1" 129 | usage 130 | ;; 131 | esac 132 | done 133 | 134 | if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; then 135 | echoerr "Error: you need to provide a host and port to test." 136 | usage 137 | fi 138 | 139 | WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15} 140 | WAITFORIT_STRICT=${WAITFORIT_STRICT:-0} 141 | WAITFORIT_CHILD=${WAITFORIT_CHILD:-0} 142 | WAITFORIT_QUIET=${WAITFORIT_QUIET:-0} 143 | 144 | # check to see if timeout is from busybox? 145 | WAITFORIT_TIMEOUT_PATH=$(type -p timeout) 146 | WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH) 147 | if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then 148 | WAITFORIT_ISBUSY=1 149 | WAITFORIT_BUSYTIMEFLAG="-t" 150 | 151 | else 152 | WAITFORIT_ISBUSY=0 153 | WAITFORIT_BUSYTIMEFLAG="" 154 | fi 155 | 156 | if [[ $WAITFORIT_CHILD -gt 0 ]]; then 157 | wait_for 158 | WAITFORIT_RESULT=$? 159 | exit $WAITFORIT_RESULT 160 | else 161 | if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then 162 | wait_for_wrapper 163 | WAITFORIT_RESULT=$? 164 | else 165 | wait_for 166 | WAITFORIT_RESULT=$? 167 | fi 168 | fi 169 | 170 | if [[ $WAITFORIT_CLI != "" ]]; then 171 | if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then 172 | echoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess" 173 | exit $WAITFORIT_RESULT 174 | fi 175 | exec "${WAITFORIT_CLI[@]}" 176 | else 177 | exit $WAITFORIT_RESULT 178 | fi 179 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zls-docker 2 | 3 | 开箱即用的面向生产和开发环境的 Docker 镜像 4 | 5 | [详细文档](https://docs.73zls.com/zls-docker/#/) 6 | 7 | ## 目录结构 8 | 9 | ``` 10 | . 11 | ├── config 12 | │   ├── mysql 13 | │   │   └── mysql.cnf mysql.cnf 配置 14 | │   ├── caddy caddy 配置目录 15 | │   ├── nginx 16 | │   │   ├── conf.d vhost 配置目录 17 | │   │   │   ├── localhost.conf 默认站点配置 18 | │   │   │   └── localhost_https.conf 默认站点HTTPS配置 19 | │   │   └── nginx.conf nginx.conf 配置 20 | │   ├── php 21 | │   │   ├── php-fpm.conf php-fpm.conf 配置 22 | │   │   └── php.ini php.ini 配置 23 | │   ├── redis 24 | │   │ └── redis.conf redis.conf 配置 25 | │   ├── lua lua 脚本 26 | │   │ └── waf 27 | │   │ └── config.lua web 防火墙配置 28 | ├── data 数据目录 29 | ├── logs 日志目录 30 | ├── docker-compose.yml docker-compose 编排文件 31 | ├── run.sh 执行脚本 32 | └── www 站点目录 33 | └── localhost 默认站点 34 | ``` 35 | 36 | ## 快速上手 37 | 38 | 1. 安装 git、 docker 和 docker-compose 39 | 40 | docker >=19 41 | 42 | docker-compose >= 3 43 | 44 | 系统自带的 yum、apt 安装版本可能会过低了, 45 | 46 | 如不清楚如果不熟悉怎么安装 docker, 47 | 48 | 执行可以拉取项目后执行 ./run.sh installDocker 查看相关安装命令, 49 | 50 | 或查看 [docker.md](./docker.md) 参考安装步骤。 51 | 52 | 2. 拉取项目 53 | 54 | ```bash 55 | git clone --depth=1 https://github.com/sohaha/zls-docker.git 56 | ``` 57 | 58 | 3. 启动 59 | 60 | *默认配置使用 nginx 与 caddy 只能启动其中一个。* 61 | 62 | ```bash 63 | # 更多命令直接执行 run.sh 查看 64 | ./run.sh up 65 | 66 | # Windows 请先复制配置再执行启动命令 67 | copy .env.example .env 68 | copy docker-compose.yml.example docker-compose.yml 69 | docker-compose up -d nginx mysql php 70 | ``` 71 | 72 | 5. 访问在浏览器中访问 http://localhost/ 。 73 | 74 | ## 配置设置 75 | 76 | 更多配置请打开 .env 文件查看。 77 | 78 | ### PHP 使用 79 | 80 | **安装扩展** 81 | 82 | ```bash 83 | # 编辑.env文件, 84 | # 从扩展列表 PHP extensions 中选择相应的扩展, 85 | # 添加(移除)到 PHP_EXTENSIONS 中,英文逗号隔开 86 | PHP_EXTENSIONS=swoole,redis 87 | 88 | # 重新编译 PHP 镜像并启动 89 | ./run.sh buildUp php 90 | 91 | # Windows 请执行 docker-compose build php && docker-compose up php -d 92 | ``` 93 | 94 | ### 定时任务 95 | 96 | 有些时候需要配置定时任务做一些特定业务处理,但是直接在容器内是不支持的,不过我们可以直接在宿主机上设置。 97 | 98 | !> 请确定 crontab 下 docker-compose 能正常使用,如果不能请尝试执行 `sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose` 再试。 99 | 100 | ```bash 101 | # 假设本脚本放在 /root/zls-docker 目录下 102 | # 需要每分钟执行一次 www/test/task.php 103 | 104 | # crontab -e 105 | # 下面语句就是每分钟进入 php 容器 执行 `php test/task.php` 106 | * * * * * /root/zls-docker/run.sh cron php php test/task.php 107 | ``` 108 | 109 | ### 数据库使用 110 | 111 | - 在其它容器需要连接数据库 HOST 直接填容器名,如使用 MySQL: mysql 即可(或 172.0.0.20)。 112 | 113 | - 如需修改默认密码,编辑.env 文件即可, 114 | 115 | MySQL:`MYSQL_ROOT_PASSWORD=73zls666`, 116 | 117 | mongo:`MONGODB_INITDB_ROOT_PASSWORD=73zls666` 118 | 119 | 必须在容器生成之前,如果容器已经生成过, 120 | 121 | 请使用 bash 进入容器内修改,具体方法请谷歌。 122 | 123 | - Msqyl 建立新数据库直接执行: `zdc mysql` 然后选 3( Create Databases )即可。 124 | 125 | --- 126 | 127 | ## 日常使用 128 | 129 | ### 安装脚本 130 | 131 | 建议把脚本命令安装至系统中,方便使用 132 | 133 | ```bash 134 | ./run.sh tools 135 | # 输入1,自动安装至系统,然后就可以全局使用 zdocker 136 | 137 | zdocker help 138 | ``` 139 | 140 | ### 命令行 141 | 142 | 如要使用 composer,启动 swoole ,或 npm 安装等等。 143 | 144 | ```bash 145 | ./run.sh composer install zls/wechat 146 | ./run.sh php test.php 147 | ./run.sh npm install zls-ui 148 | ./run.sh go build 149 | ... 150 | ``` 151 | 152 | ### 重新加载 153 | 154 | nginx,php-fpm 之类的修改了配置是需要重新加载的,可使用该命令 155 | 156 | ```bash 157 | # 不值得容器默认为nginx,下面命令等同 ./run.sh reload nginx 158 | ./run.sh reload 159 | 160 | ./run.sh reload php 161 | ``` 162 | 163 | ### 进入容器 164 | 165 | ```bash 166 | # ./run.sh bash 容器名称,如ph 167 | ./run.sh bash php 168 | ``` 169 | 170 | ### 停止容器 171 | 172 | ```bash 173 | # ./run.sh stop 容器名称(空表示停止全部) 174 | ./run.sh stop nginx 175 | ``` 176 | 177 | ### 辅助操作 178 | 179 | 一些常用的操作,如 php-fpm 优化,清理没用使用的容器等等 180 | 181 | ```bash 182 | ./run.sh tools 183 | ``` 184 | 185 | ### HTTPS 证书 186 | 187 | **首次使用** 188 | 189 | ```bash 190 | # 如果首次执行失败,建议先把签证服务修改为 letsencrypt 191 | ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt 192 | ``` 193 | 194 | ```bash 195 | # ./run.sh ssl -d 要签名的域名 -w 服务器里项目访问路径 196 | ./run.sh ssl -d mydomain.com -w /home/zdocker/www/mydomain.com/public 197 | 198 | # 证书生成成功会自动拷贝一份到 /config/nginx/conf.d/certs/mydomain.com/ 目录 199 | # https 的配置可以参考 config/nginx/conf.d/localhost_https.conf 200 | ``` 201 | 202 | ### 更多问题 203 | 204 | **数据库安全** 205 | 206 | 默认情况数据库是禁止外部连接的,如果需要开启请修改 .env 中的 MySQL 配置, 207 | 把 `MYSQL_HOST_PORT=127.0.0.1:3306` 改成 `MYSQL_HOST_PORT=3306` 208 | 209 | ```mysql 210 | # 为了安全性建议把 %.root 的密码修改成其他密码(默认密码:73zls666) 211 | ALTER USER `root`@`%` IDENTIFIED BY 'xxx1990hi',`root`@`%` PASSWORD EXPIRE NEVER; 212 | ``` 213 | 214 | **数据库备份** 215 | 建议设置定时任务,定时备份数据库,如下: 216 | 217 | ```bash 218 | # 假设本脚本放在 /root/zls-docker 目录下 219 | # crontab -e 220 | 221 | # 每天凌晨三点备份 MySQL 数据库 222 | 00 03 * * * /root/zls-docker/run.sh mysql backup 223 | 224 | # 每天凌晨三点备份 MongoDB 数据库 225 | 00 03 * * * /root/zls-docker/run.sh mongodb backup 226 | 227 | ``` 228 | 229 | **MongoDB 启动失败** 230 | 231 | ``` 232 | /data/db/WiredTiger.wt: handle-open: open: Operation not permitted 233 | ``` 234 | 235 | 原因: Windows 下不支持映射目录 236 | 237 | 解决方案: 注释掉 `docker-compose.yml` 文件内的 `mongodb` 映射配置, 238 | 239 | `# - ${MONGODB_DATA_DIR}:/data/db:rw` 240 | 241 | **Swoole 版本** 242 | 243 | 默认情况安装的是最新版的 Swoole, 如果需要指定版本直接修改安装脚本 `config/php/extensions/php.sh` 244 | 245 | **启动失败** 246 | 247 | 查看 logs 目录,参考日志信息处理。 248 | 249 | **安装 sentry** 250 | 251 | 首次启动之后需要初始化数据库,然后访问 http://127.0.0.1:9000 。 252 | 253 | ```bash 254 | # 首次启动一定一定要修改 SENTRY_SECRET_KEY ,下面这条命令可以动态生成一个 SECRET_KEY 255 | # docker run --rm sentry config generate-secret-key 256 | # 初始化数据库,过程需要填写邮箱与密码 257 | zdc bash sentry sentry upgrade 258 | ``` 259 | 260 | **安装 YAPI** 261 | 262 | ```bash 263 | # 先启动 mongodb 264 | ./run.sh up mongodb 265 | 266 | # 进入 mogodb 内 建立 Yapi 账号 267 | ./run.sh bash mongodb 268 | # 进入 mongo 数据库 269 | mongo -u root -p 73zls666 270 | # 进入 Yapi 库 271 | use yapi 272 | # 添加一个用户 然后 Ctrl+c退出数据库 exit 退出容器 273 | db.createUser({user: "yapi",pwd: "73zls666",roles: [{role: "dbOwner",db: "yapi"}]}) 274 | # 默认账号密码 admin@admin.com ymfe.org 275 | # 启动 yapi (上面步骤只要执行一次) 276 | ./run.sh up yapi 277 | 278 | ``` 279 | 280 | **安装监控服务** 281 | 282 | 默认包含 grafana、prometheus、mysqlexporter。 283 | 284 | 注意: 如果你是 Root 用户启动,首次启动之前需要先给数据目录写入权限 285 | 286 | ```bash 287 | chmod 777 ./data/grafana 288 | chmod 777 ./data/prometheus 289 | ``` 290 | 291 | 启动命令: zdc up grafana, 292 | 293 | 然后访问 http://127.0.0.1:3010/ ( 默认账号 admin/admin666 )。 294 | 295 | 配置 MySQL dashboard: 296 | 297 | 首先添加 Data Sources 选 Prometheus , 298 | 299 | URL填: http://prometheus:9090 ,其他的默认保存即可, 300 | 301 | 然后复制 `config/grafana/mysql-dashboard.json` 内容,贴贴到 ‘Import via panel json’ 创建完成。 302 | 303 | 如需监控服务器性能: 304 | 305 | 需手动启动(需要 docker root 权限) `zdc up nodeexporter`,再 `Import via grafana.com` 编码 8919。 306 | -------------------------------------------------------------------------------- /config/php/extensions/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo 4 | echo "============================================" 5 | echo "Install extensions from : install.sh" 6 | echo "Extra Extensions : ${PHP_EXTENSIONS}" 7 | echo "Multicore Compilation : ${MC}" 8 | echo "Work directory : ${PWD}" 9 | echo "============================================" 10 | echo 11 | 12 | 13 | if [ "${ALPINE_REPOSITORIES}" != "" ]; then 14 | sed -i "s/dl-cdn.alpinelinux.org/${ALPINE_REPOSITORIES}/g" /etc/apk/repositories 15 | fi 16 | 17 | 18 | if [ "${PHP_EXTENSIONS}" != "" ]; then 19 | echo "---------- Install general dependencies ----------" 20 | apk add --no-cache autoconf g++ libtool make curl-dev libxml2-dev linux-headers 21 | fi 22 | 23 | if [ -z "${EXTENSIONS##*,pdo_mysql,*}" ]; then 24 | echo "---------- Install pdo_mysql ----------" 25 | docker-php-ext-install ${MC} pdo_mysql 26 | fi 27 | 28 | if [ -z "${EXTENSIONS##*,zip,*}" ]; then 29 | echo "---------- Install zip ----------" 30 | apk add --no-cache libzip-dev 31 | docker-php-ext-install ${MC} zip 32 | fi 33 | 34 | if [ -z "${EXTENSIONS##*,pcntl,*}" ]; then 35 | echo "---------- Install pcntl ----------" 36 | docker-php-ext-install ${MC} pcntl 37 | fi 38 | 39 | if [ -z "${EXTENSIONS##*,mysqli,*}" ]; then 40 | echo "---------- Install mysqli ----------" 41 | docker-php-ext-install ${MC} mysqli 42 | fi 43 | 44 | if [ -z "${EXTENSIONS##*,mbstring,*}" ]; then 45 | echo "---------- Install mbstring ----------" 46 | docker-php-ext-install ${MC} mbstring 47 | fi 48 | 49 | if [ -z "${EXTENSIONS##*,exif,*}" ]; then 50 | echo "---------- Install exif ----------" 51 | docker-php-ext-install ${MC} exif 52 | fi 53 | 54 | if [ -z "${EXTENSIONS##*,bcmath,*}" ]; then 55 | echo "---------- Install bcmath ----------" 56 | docker-php-ext-install ${MC} bcmath 57 | fi 58 | 59 | if [ -z "${EXTENSIONS##*,calendar,*}" ]; then 60 | echo "---------- Install calendar ----------" 61 | docker-php-ext-install ${MC} calendar 62 | fi 63 | 64 | if [ -z "${EXTENSIONS##*,zend_test,*}" ]; then 65 | echo "---------- Install zend_test ----------" 66 | docker-php-ext-install ${MC} zend_test 67 | fi 68 | 69 | if [ -z "${EXTENSIONS##*,opcache,*}" ]; then 70 | echo "---------- Install opcache ----------" 71 | docker-php-ext-install opcache 72 | fi 73 | 74 | if [ -z "${EXTENSIONS##*,sockets,*}" ]; then 75 | echo "---------- Install sockets ----------" 76 | docker-php-ext-install ${MC} sockets 77 | fi 78 | 79 | if [ -z "${EXTENSIONS##*,gettext,*}" ]; then 80 | echo "---------- Install gettext ----------" 81 | docker-php-ext-install ${MC} gettext 82 | fi 83 | 84 | if [ -z "${EXTENSIONS##*,shmop,*}" ]; then 85 | echo "---------- Install shmop ----------" 86 | docker-php-ext-install ${MC} shmop 87 | fi 88 | 89 | if [ -z "${EXTENSIONS##*,sysvmsg,*}" ]; then 90 | echo "---------- Install sysvmsg ----------" 91 | docker-php-ext-install ${MC} sysvmsg 92 | fi 93 | 94 | if [ -z "${EXTENSIONS##*,sysvsem,*}" ]; then 95 | echo "---------- Install sysvsem ----------" 96 | docker-php-ext-install ${MC} sysvsem 97 | fi 98 | 99 | if [ -z "${EXTENSIONS##*,sysvshm,*}" ]; then 100 | echo "---------- Install sysvshm ----------" 101 | docker-php-ext-install ${MC} sysvshm 102 | fi 103 | 104 | if [ -z "${EXTENSIONS##*,pdo_firebird,*}" ]; then 105 | echo "---------- Install pdo_firebird ----------" 106 | docker-php-ext-install ${MC} pdo_firebird 107 | fi 108 | 109 | if [ -z "${EXTENSIONS##*,pdo_dblib,*}" ]; then 110 | echo "---------- Install pdo_dblib ----------" 111 | docker-php-ext-install ${MC} pdo_dblib 112 | fi 113 | 114 | if [ -z "${EXTENSIONS##*,pdo_oci,*}" ]; then 115 | echo "---------- Install pdo_oci ----------" 116 | docker-php-ext-install ${MC} pdo_oci 117 | fi 118 | 119 | if [ -z "${EXTENSIONS##*,pdo_odbc,*}" ]; then 120 | echo "---------- Install pdo_odbc ----------" 121 | docker-php-ext-install ${MC} pdo_odbc 122 | fi 123 | 124 | if [ -z "${EXTENSIONS##*,pdo_pgsql,*}" ]; then 125 | echo "---------- Install pdo_pgsql ----------" 126 | apk --no-cache add postgresql-dev \ 127 | && docker-php-ext-install ${MC} pdo_pgsql 128 | fi 129 | 130 | if [ -z "${EXTENSIONS##*,pgsql,*}" ]; then 131 | echo "---------- Install pgsql ----------" 132 | apk --no-cache add postgresql-dev \ 133 | && docker-php-ext-install ${MC} pgsql 134 | fi 135 | 136 | if [ -z "${EXTENSIONS##*,oci8,*}" ]; then 137 | echo "---------- Install oci8 ----------" 138 | docker-php-ext-install ${MC} oci8 139 | fi 140 | 141 | if [ -z "${EXTENSIONS##*,odbc,*}" ]; then 142 | echo "---------- Install odbc ----------" 143 | docker-php-ext-install ${MC} odbc 144 | fi 145 | 146 | if [ -z "${EXTENSIONS##*,dba,*}" ]; then 147 | echo "---------- Install dba ----------" 148 | docker-php-ext-install ${MC} dba 149 | fi 150 | 151 | if [ -z "${EXTENSIONS##*,interbase,*}" ]; then 152 | echo "---------- Install interbase ----------" 153 | echo "Alpine linux do not support interbase/firebird!!!" 154 | #docker-php-ext-install ${MC} interbase 155 | fi 156 | 157 | if [ -z "${EXTENSIONS##*,gd,*}" ]; then 158 | echo "---------- Install gd ----------" 159 | apk add --no-cache freetype-dev libjpeg-turbo-dev libpng-dev \ 160 | && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \ 161 | && docker-php-ext-install ${MC} gd 162 | fi 163 | 164 | if [ -z "${EXTENSIONS##*,intl,*}" ]; then 165 | echo "---------- Install intl ----------" 166 | apk add --no-cache icu-dev 167 | docker-php-ext-install ${MC} intl 168 | fi 169 | 170 | if [ -z "${EXTENSIONS##*,bz2,*}" ]; then 171 | echo "---------- Install bz2 ----------" 172 | apk add --no-cache bzip2-dev 173 | docker-php-ext-install ${MC} bz2 174 | fi 175 | 176 | if [ -z "${EXTENSIONS##*,soap,*}" ]; then 177 | echo "---------- Install soap ----------" 178 | docker-php-ext-install ${MC} soap 179 | fi 180 | 181 | if [ -z "${EXTENSIONS##*,xsl,*}" ]; then 182 | echo "---------- Install xsl ----------" 183 | apk add --no-cache libxslt-dev 184 | docker-php-ext-install ${MC} xsl 185 | fi 186 | 187 | if [ -z "${EXTENSIONS##*,xmlrpc,*}" ]; then 188 | echo "---------- Install xmlrpc ----------" 189 | apk add --no-cache libxslt-dev 190 | docker-php-ext-install ${MC} xmlrpc 191 | fi 192 | 193 | if [ -z "${EXTENSIONS##*,wddx,*}" ]; then 194 | echo "---------- Install wddx ----------" 195 | apk add --no-cache libxslt-dev 196 | docker-php-ext-install ${MC} wddx 197 | fi 198 | 199 | if [ -z "${EXTENSIONS##*,curl,*}" ]; then 200 | echo "---------- Install curl ----------" 201 | docker-php-ext-install ${MC} curl 202 | fi 203 | 204 | if [ -z "${EXTENSIONS##*,readline,*}" ]; then 205 | echo "---------- Install readline ----------" 206 | apk add --no-cache readline-dev 207 | apk add --no-cache libedit-dev 208 | docker-php-ext-install ${MC} readline 209 | fi 210 | 211 | if [ -z "${EXTENSIONS##*,snmp,*}" ]; then 212 | echo "---------- Install snmp ----------" 213 | apk add --no-cache net-snmp-dev 214 | docker-php-ext-install ${MC} snmp 215 | fi 216 | 217 | if [ -z "${EXTENSIONS##*,pspell,*}" ]; then 218 | echo "---------- Install pspell ----------" 219 | apk add --no-cache aspell-dev 220 | apk add --no-cache aspell-en 221 | docker-php-ext-install ${MC} pspell 222 | fi 223 | 224 | if [ -z "${EXTENSIONS##*,recode,*}" ]; then 225 | echo "---------- Install recode ----------" 226 | apk add --no-cache recode-dev 227 | docker-php-ext-install ${MC} recode 228 | fi 229 | 230 | if [ -z "${EXTENSIONS##*,tidy,*}" ]; then 231 | echo "---------- Install tidy ----------" 232 | apk add --no-cache tidyhtml-dev=5.2.0-r1 --repository http://${ALPINE_REPOSITORIES}/alpine/v3.6/community 233 | docker-php-ext-install ${MC} tidy 234 | fi 235 | 236 | if [ -z "${EXTENSIONS##*,gmp,*}" ]; then 237 | echo "---------- Install gmp ----------" 238 | apk add --no-cache gmp-dev 239 | docker-php-ext-install ${MC} gmp 240 | fi 241 | 242 | if [ -z "${EXTENSIONS##*,imap,*}" ]; then 243 | echo "---------- Install imap ----------" 244 | apk add --no-cache imap-dev 245 | docker-php-ext-configure imap --with-imap --with-imap-ssl 246 | docker-php-ext-install ${MC} imap 247 | fi 248 | 249 | if [ -z "${EXTENSIONS##*,ldap,*}" ]; then 250 | echo "---------- Install ldap ----------" 251 | apk add --no-cache ldb-dev 252 | apk add --no-cache openldap-dev 253 | docker-php-ext-install ${MC} ldap 254 | fi 255 | 256 | if [ -z "${EXTENSIONS##*,imagick,*}" ]; then 257 | echo "---------- Install imagick ----------" 258 | apk add --no-cache file-dev 259 | apk add --no-cache imagemagick-dev 260 | printf "\n" | pecl install imagick-3.4.4 261 | docker-php-ext-enable imagick 262 | fi 263 | 264 | -------------------------------------------------------------------------------- /config/lua/waf/init.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Author: seekwe 3 | Date: 2019-10-27 18:24:58 4 | Last Modified by:: seekwe 5 | Last Modified time: 2020-08-14 20:47:22 6 | --]] 7 | 8 | require 'config' 9 | local match = string.match 10 | local ngxmatch=ngx.re.match 11 | local unescape=ngx.unescape_uri 12 | local get_headers = ngx.req.get_headers 13 | local optionIsOn = function (options) return options == "on" and true or false end 14 | logpath = Logdir 15 | rulepath = RulePath 16 | UrlDeny = optionIsOn(UrlDeny) 17 | PostCheck = optionIsOn(PostMatch) 18 | CookieCheck = optionIsOn(CookieMatch) 19 | WhiteCheck = optionIsOn(WhiteModule) 20 | WhiteHostCheck = optionIsOn(WhiteHostModule) 21 | PathInfoFix = optionIsOn(PathInfoFix) 22 | Attacklog = optionIsOn(Attacklog) 23 | CCDeny = optionIsOn(CCDeny) 24 | Redirect=optionIsOn(Redirect) 25 | function getClientIp() 26 | IP = ngx.req.get_headers()["X-Real-IP"] 27 | if IP == nil then 28 | IP = ngx.var.remote_addr 29 | end 30 | if IP == nil then 31 | IP = "unknown" 32 | end 33 | return IP 34 | end 35 | function write(logfile,msg) 36 | local fd = io.open(logfile,"ab") 37 | if fd == nil then return end 38 | fd:write(msg) 39 | fd:flush() 40 | fd:close() 41 | end 42 | function log(method,url,data,ruletag) 43 | if Attacklog then 44 | local realIp = getClientIp() 45 | local ua = ngx.var.http_user_agent 46 | local servername=ngx.var.server_name 47 | local time=ngx.localtime() 48 | if ua then 49 | line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\" \""..ua.."\" \""..ruletag.."\"\n" 50 | else 51 | line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\" - \""..ruletag.."\"\n" 52 | end 53 | local filename = logpath..'/waf_'..servername.."_"..ngx.today().."_sec.log" 54 | write(filename,line) 55 | end 56 | end 57 | 58 | function ipToDecimal(ckip) 59 | local n = 4 60 | local decimalNum = 0 61 | local pos = 0 62 | for s, e in function() return string.find(ckip, '.', pos, true) end do 63 | n = n - 1 64 | decimalNum = decimalNum + string.sub(ckip, pos, s-1) * (256 ^ n) 65 | pos = e + 1 66 | if n == 1 then decimalNum = decimalNum + string.sub(ckip, pos, string.len(ckip)) end 67 | end 68 | return decimalNum 69 | end 70 | ------------------------------------规则读取函数------------------------------------------------------------------- 71 | function read_rule(var) 72 | file = io.open(rulepath..'/'..var,"r") 73 | if file==nil then 74 | local info = debug.getinfo(1, "S") 75 | local path = info.source 76 | path = string.sub(path, 2, -1) 77 | path = string.match(path, "^.*/") 78 | file = io.open(path..rulepath..'/'..var,"r") 79 | if file==nil then 80 | return 81 | end 82 | end 83 | t = {} 84 | for line in file:lines() do 85 | table.insert(t,line) 86 | end 87 | file:close() 88 | return(t) 89 | end 90 | 91 | urlrules=read_rule('url') 92 | argsrules=read_rule('args') 93 | uarules=read_rule('user-agent') 94 | whiteuarules=read_rule('white-user-agent') 95 | wturlrules=read_rule('whiteurl') 96 | postrules=read_rule('post') 97 | ckrules=read_rule('cookie') 98 | 99 | function say_html() 100 | if Redirect then 101 | ngx.header.content_type = "text/html;charset=utf8" 102 | ngx.say(Html) 103 | ngx.exit(200) 104 | end 105 | end 106 | 107 | function whiteurl() 108 | if WhiteCheck then 109 | if wturlrules ~=nil then 110 | for _,rule in pairs(wturlrules) do 111 | if ngxmatch(ngx.var.request_uri,rule,"isjo") then 112 | return true 113 | end 114 | end 115 | end 116 | end 117 | return false 118 | end 119 | 120 | function whitehost() 121 | if WhiteHostCheck then 122 | local items = Set(HostWhiteList) 123 | for host in pairs(items) do 124 | if ngxmatch(ngx.var.host, host, "isjo") then 125 | log('POST',ngx.var.request_uri,"-","white host".. host) 126 | return true 127 | end 128 | end 129 | end 130 | return false 131 | end 132 | 133 | function args() 134 | for _,rule in pairs(argsrules) do 135 | local args = ngx.req.get_uri_args() 136 | for key, val in pairs(args) do 137 | if type(val)=='table' then 138 | if val == false then 139 | data=table.concat(val, " ") 140 | end 141 | else 142 | data=val 143 | end 144 | if data and type(data) ~= "boolean" and rule ~="" and ngxmatch(unescape(data),rule,"isjo") then 145 | log('GET',ngx.var.request_uri,"-",rule) 146 | say_html() 147 | return true 148 | end 149 | end 150 | end 151 | return false 152 | end 153 | 154 | function url() 155 | if UrlDeny then 156 | for _,rule in pairs(urlrules) do 157 | if rule ~="" and ngxmatch(ngx.var.request_uri,rule,"isjo") then 158 | log('GET',ngx.var.request_uri,"-",rule) 159 | say_html() 160 | return true 161 | end 162 | end 163 | end 164 | return false 165 | end 166 | 167 | function ua() 168 | local ua = ngx.var.http_user_agent 169 | if ua ~= nil then 170 | for _,rule in pairs(uarules) do 171 | if rule ~="" and ngxmatch(ua,rule,"isjo") then 172 | log('UA',ngx.var.request_uri,"-",rule) 173 | say_html() 174 | return true 175 | end 176 | end 177 | end 178 | return false 179 | end 180 | 181 | function body(data) 182 | for _,rule in pairs(postrules) do 183 | if rule ~="" and data~="" and ngxmatch(unescape(data),rule,"isjo") then 184 | log('POST',ngx.var.request_uri,data,rule) 185 | say_html() 186 | return true 187 | end 188 | end 189 | return false 190 | end 191 | 192 | function cookie() 193 | local ck = ngx.var.http_cookie 194 | if CookieCheck and ck then 195 | for _,rule in pairs(ckrules) do 196 | if rule ~="" and ngxmatch(ck,rule,"isjo") then 197 | log('Cookie',ngx.var.request_uri,"-",rule) 198 | say_html() 199 | return true 200 | end 201 | end 202 | end 203 | return false 204 | end 205 | 206 | function denycc() 207 | if CCDeny then 208 | local uri=ngx.var.uri 209 | CCcount=tonumber(string.match(CCrate,'(.*)/')) 210 | CCseconds=tonumber(string.match(CCrate,'/(.*)')) 211 | local token = getClientIp()..uri 212 | local limit = ngx.shared.limit 213 | local req,_=limit:get(token) 214 | if req then 215 | if req >= CCcount then 216 | ngx.exit(503) 217 | return true 218 | else 219 | limit:incr(token,1) 220 | end 221 | else 222 | limit:set(token,1,CCseconds) 223 | end 224 | end 225 | return false 226 | end 227 | 228 | function whiteua() 229 | local ua = ngx.var.http_user_agent 230 | if ua ~= nil then 231 | for _,rule in pairs(whiteuarules) do 232 | if rule ~="" and ngxmatch(ua,rule,"isjo") then 233 | return true 234 | end 235 | end 236 | end 237 | return false 238 | end 239 | 240 | function get_boundary() 241 | local header = get_headers()["content-type"] 242 | if not header then 243 | return nil 244 | end 245 | 246 | if type(header) == "table" then 247 | header = header[1] 248 | end 249 | 250 | local m = match(header, ";%s*boundary=\"([^\"]+)\"") 251 | if m then 252 | return m 253 | end 254 | 255 | return match(header, ";%s*boundary=([^\",;]+)") 256 | end 257 | 258 | function blockip() 259 | if next(IpBlocklist) ~= nil then 260 | local cIP = getClientIp() 261 | local numIP = 0 262 | if cIP ~= "unknown" then numIP = tonumber(ipToDecimal(cIP)) end 263 | for _,ip in pairs(IpBlocklist) do 264 | local s, e = string.find(ip, '-', 0, true) 265 | if s == nil and cIP == ip then 266 | ngx.exit(403) 267 | return true 268 | elseif s ~= nil then 269 | sIP = tonumber(ipToDecimal(string.sub(ip, 0, s - 1))) 270 | eIP = tonumber(ipToDecimal(string.sub(ip, e + 1, string.len(ip)))) 271 | if numIP >= sIP and numIP <= eIP then 272 | ngx.exit(403) 273 | return true 274 | end 275 | end 276 | end 277 | end 278 | return false 279 | end 280 | 281 | function fileExtCheck(ext) 282 | local items = Set(BlackFileExt) 283 | ext=string.lower(ext) 284 | if ext then 285 | for rule in pairs(items) do 286 | if ngx.re.match(ext,rule,"isjo") then 287 | log('POST',ngx.var.request_uri,"-","file attack with ext "..ext) 288 | say_html() 289 | end 290 | end 291 | end 292 | return false 293 | end 294 | function Set (list) 295 | local set = {} 296 | for _, l in ipairs(list) do set[l] = true end 297 | return set 298 | end 299 | 300 | function whiteip() 301 | if next(IpWhitelist) ~= nil then 302 | local cIP = getClientIp() 303 | local numIP = 0 304 | if cIP ~= "unknown" then numIP = tonumber(ipToDecimal(cIP)) end 305 | for _,ip in pairs(IpWhitelist) do 306 | local s, e = string.find(ip, '-', 0, true) 307 | if s == nil and cIP == ip then 308 | return true 309 | elseif s ~= nil then 310 | sIP = tonumber(ipToDecimal(string.sub(ip, 0, s - 1))) 311 | eIP = tonumber(ipToDecimal(string.sub(ip, e + 1, string.len(ip)))) 312 | if numIP >= sIP and numIP <= eIP then 313 | return true 314 | end 315 | end 316 | end 317 | end 318 | return false 319 | end 320 | 321 | 322 | 323 | 324 | -------------------------------------------------------------------------------- /docker-compose.yml.example: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | networks: 4 | defNetworks: 5 | driver: bridge 6 | ipam: 7 | config: 8 | - subnet: 172.0.0.0/24 9 | 10 | services: 11 | ### ubuntu ########## 12 | ubuntu: 13 | build: 14 | context: ./config/ubuntu/ 15 | args: 16 | UBUNTU_IMAGES: ${UBUNTU_IMAGES} 17 | network_mode: host 18 | command: tail -F /dev/null 19 | volumes: 20 | - ${SOURCE_DIR}:/var/www/html/:rw 21 | 22 | ### node ########## 23 | node: 24 | build: 25 | context: ./config/node/ 26 | args: 27 | NODE_IMAGES: ${NODE_IMAGES} 28 | environment: 29 | TZ: Asia/Shanghai 30 | volumes: 31 | - ${SOURCE_DIR}:/var/www/html/:rw 32 | networks: 33 | - defNetworks 34 | 35 | ### go ########## 36 | go: 37 | build: 38 | context: ./config/golang/ 39 | args: 40 | GO_IMAGES: ${GO_IMAGES} 41 | volumes: 42 | - ${SOURCE_DIR}:/var/www/html/:rw 43 | environment: 44 | TZ: Asia/Shanghai 45 | networks: 46 | - defNetworks 47 | 48 | ### nginx ########## 49 | nginx: 50 | build: 51 | context: ./config/nginx/ 52 | args: 53 | NGINX_IMAGES: ${NGINX_IMAGES} 54 | ports: 55 | - "${NGINX_HTTP_HOST_PORT}:80" 56 | - "${NGINX_HTTPS_HOST_PORT}:443" 57 | volumes: 58 | - ${SOURCE_DIR}:/var/www/html/:rw 59 | - ${NGINX_LOG_DIR}:/var/log/nginx/:rw 60 | - ${NGINX_CONFD_DIR}:/etc/nginx/conf.d/:rw 61 | - ${LUA_DIR}:/usr/local/openresty/nginx/conf/lua:rw 62 | - ${NGINX_CONF_FILE}:/etc/nginx/nginx.conf:ro 63 | - ${NGINX_CONF_FILE}:/usr/local/openresty/nginx/conf/nginx.conf:ro 64 | restart: on-failure 65 | depends_on: 66 | - php 67 | environment: 68 | MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD}" 69 | REDIS_PASSWORD: "${REDIS_PASSWORD}" 70 | TZ: Asia/Shanghai 71 | networks: 72 | defNetworks: 73 | ipv4_address: 172.0.0.10 74 | 75 | ### caddy ########## 76 | caddy: 77 | build: 78 | context: ./config/caddy/ 79 | args: 80 | CADDY_IMAGES: ${CADDY_IMAGES} 81 | ports: 82 | - "${CADDY_HTTP_HOST_PORT}:80" 83 | - "${CADDY_HTTPS_HOST_PORT}:443" 84 | volumes: 85 | - ${SOURCE_DIR}:/var/www/html/:rw 86 | - ${CADDY_CONF_DIR}/Caddyfile:/etc/caddy/Caddyfile:rw 87 | - ${CADDY_CONF_DIR}/vhosts:/etc/caddy/vhosts:rw 88 | - ${CADDY_SSL_DIR}:/data/caddy/certificates/:rw 89 | - ${CADDY_LOG_DIR}:/tmp/caddylog:rw 90 | restart: on-failure 91 | depends_on: 92 | - php 93 | environment: 94 | MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD}" 95 | REDIS_PASSWORD: "${REDIS_PASSWORD}" 96 | TZ: Asia/Shanghai 97 | DNSPOD_TOKEN: "id,token" 98 | networks: 99 | defNetworks: 100 | ipv4_address: 172.0.0.11 101 | 102 | ### php ########## 103 | php: 104 | build: 105 | context: ./config/php/ 106 | args: 107 | PHP_IMAGES: ${PHP_IMAGES} 108 | ALPINE_REPOSITORIES: ${ALPINE_REPOSITORIES} 109 | PHP_EXTENSIONS: ${PHP_EXTENSIONS} 110 | COMPOSER_VERSION: ${COMPOSER_VERSION} 111 | COMPOSER_PACKAGIST: ${COMPOSER_PACKAGIST} 112 | MORE_EXTENSION_INSTALLER: php.sh 113 | volumes: 114 | - ${SOURCE_DIR}:/var/www/html/:rw 115 | - ${PHP_PHP_CONF_FILE}:/usr/local/etc/php/php.ini:ro 116 | - ${PHP_FPM_CONF_FILE}:/usr/local/etc/php-fpm.d/www.conf:rw 117 | - ${PHP_LOG_DIR}:/var/log/php 118 | - ${COMPOSER_DATA_DIR}:/composer:rw 119 | - ${NGINX_CONFD_DIR}:/etc/nginx/conf.d/:rw 120 | restart: on-failure 121 | environment: 122 | MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD}" 123 | REDIS_PASSWORD: "${REDIS_PASSWORD}" 124 | TZ: Asia/Shanghai 125 | cap_add: 126 | - SYS_PTRACE 127 | networks: 128 | defNetworks: 129 | ipv4_address: 172.0.0.30 130 | extra_hosts: 131 | - "nginx.docker:172.0.0.10" 132 | security_opt: 133 | - "seccomp=./config/php/seccomp.json" 134 | 135 | ### mysql ########## 136 | mysql: 137 | build: 138 | context: ./config/mysql/ 139 | args: 140 | MYSQL_IMAGES: ${MYSQL_IMAGES} 141 | ports: 142 | - "${MYSQL_HOST_PORT}:3306" 143 | volumes: 144 | - ${MYSQL_CONF_FILE}:/etc/mysql/conf.d/mysql.cnf:ro 145 | - ${MYSQL_DATA_DIR}:/var/lib/mysql/:rw 146 | - ${MYSQL_CONF_DIR}:/mysql/:rw 147 | restart: on-failure 148 | networks: 149 | defNetworks: 150 | ipv4_address: 172.0.0.20 151 | environment: 152 | MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD}" 153 | MYSQL_DATABASE: "${MYSQL_DATABASE}" 154 | TZ: Asia/Shanghai 155 | 156 | ### redis ########## 157 | redis: 158 | build: 159 | context: ./config/redis/ 160 | args: 161 | REDIS_IMAGES: ${REDIS_IMAGES} 162 | ports: 163 | - "${REDIS_HOST_PORT}:6379" 164 | volumes: 165 | - ${REDIS_CONF_FILE}:/etc/redis.conf:ro 166 | restart: on-failure 167 | environment: 168 | TZ: Asia/Shanghai 169 | entrypoint: 170 | ["redis-server", "/etc/redis.conf", "--requirepass", "${REDIS_PASSWORD}"] 171 | networks: 172 | defNetworks: 173 | ipv4_address: 172.0.0.40 174 | 175 | ### mongodb ########## 176 | mongodb: 177 | build: 178 | context: ./config/mongodb/ 179 | args: 180 | MONGODB_IMAGES: ${MONGODB_IMAGES} 181 | environment: 182 | MONGO_INITDB_ROOT_USERNAME: "${MONGODB_INITDB_ROOT_USERNAME}" 183 | MONGO_INITDB_ROOT_PASSWORD: "${MONGODB_INITDB_ROOT_PASSWORD}" 184 | TZ: Asia/Shanghai 185 | volumes: 186 | - ${MONGODB_DATA_DIR}/data:/data/db:rw 187 | - ./config/mongodb/backup:/backup:rw 188 | # 配置集群 189 | # openssl rand -base64 128 > ./data/mongo/keyFile && sudo chmod 600 ./data/mongo/keyFile && sudo chown 999:999 ./data/mongo/keyFile 190 | # mongo -u root -p 73zls666 --authenticationDatabase admin 191 | # rs.initiate({_id:"rs0", members:[{_id:0, host:"x.x.x.x:27017"}]}) 192 | # rs.add("x.x.x.x:27017") 193 | # - ${MONGODB_DATA_DIR}/keyFile:/data/mongodb/keyFile:r 194 | # command: --auth --replSet rs0 --keyFile /data/mongodb/keyFile 195 | command: --auth 196 | ports: 197 | - "${MONGODB_HOST_PORT}:27017" 198 | networks: 199 | - defNetworks 200 | 201 | ### sentry ########## 202 | sentry: 203 | image: ${SENTRY_IMAGES} 204 | depends_on: 205 | - redis 206 | - postgres 207 | - sentry_celery_beat 208 | - sentry_celery_worker 209 | ports: 210 | - ${SENTRY_PORT}:9000 211 | environment: 212 | SENTRY_SECRET_KEY: "${SENTRY_SECRET_KEY}" 213 | SENTRY_REDIS_HOST: "redis" 214 | SENTRY_POSTGRES_HOST: "postgres" 215 | SENTRY_DB_USER: "${POSTGRES_USER}" 216 | SENTRY_DB_PASSWORD: "${POSTGRES_PASSWORD}" 217 | TZ: Asia/Shanghai 218 | cap_add: 219 | - SYS_PTRACE 220 | networks: 221 | - defNetworks 222 | 223 | sentry_celery_beat: 224 | image: ${SENTRY_IMAGES} 225 | depends_on: 226 | - redis 227 | - postgres 228 | command: "sentry run cron" 229 | environment: 230 | SENTRY_SECRET_KEY: "${SENTRY_SECRET_KEY}" 231 | SENTRY_REDIS_HOST: "redis" 232 | SENTRY_POSTGRES_HOST: "postgres" 233 | SENTRY_DB_USER: "${POSTGRES_USER}" 234 | SENTRY_DB_PASSWORD: "${POSTGRES_PASSWORD}" 235 | cap_add: 236 | - SYS_PTRACE 237 | networks: 238 | - defNetworks 239 | 240 | sentry_celery_worker: 241 | image: ${SENTRY_IMAGES} 242 | depends_on: 243 | - redis 244 | - postgres 245 | links: 246 | - redis 247 | - postgres 248 | command: "sentry run worker" 249 | environment: 250 | SENTRY_SECRET_KEY: "${SENTRY_SECRET_KEY}" 251 | SENTRY_REDIS_HOST: "redis" 252 | SENTRY_POSTGRES_HOST: "postgres" 253 | SENTRY_DB_USER: "${POSTGRES_USER}" 254 | SENTRY_DB_PASSWORD: "${POSTGRES_PASSWORD}" 255 | cap_add: 256 | - SYS_PTRACE 257 | networks: 258 | - defNetworks 259 | 260 | ### postgres ########## 261 | postgres: 262 | build: 263 | context: ./config/postgres 264 | args: 265 | POSTGRES_IMAGES: ${POSTGRES_IMAGES} 266 | ports: 267 | - "${POSTGRES_PORT}:5432" 268 | volumes: 269 | - ${POSTGRES_DATA_DIR}:/var/lib/postgresql/data:rw 270 | restart: on-failure 271 | environment: 272 | POSTGRES_DB: "${POSTGRES_DB}" 273 | POSTGRES_USER: "${POSTGRES_USER}" 274 | POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}" 275 | #PGDATA: /tmp 276 | TZ: Asia/Shanghai 277 | networks: 278 | - defNetworks 279 | 280 | ### portainer ########## 281 | portainer: 282 | image: ${PORTAINER_IMAGES} 283 | command: -H unix:///var/run/docker.sock 284 | restart: on-failure 285 | ports: 286 | - "${PORTAINER_HOST_PORT}:9000" 287 | environment: 288 | TZ: Asia/Shanghai 289 | volumes: 290 | - /var/run/docker.sock:/var/run/docker.sock 291 | - ${PORTAINER_DATA_DIR}:/data 292 | 293 | ### yapi ########## 294 | yapi: 295 | build: 296 | context: ./config/yapi/ 297 | args: 298 | YAPI_VERSION: ${YAPI_VERSION} 299 | YAPI_HOME: ${YAPI_HOME} 300 | YAPI_HOST_PORT: ${YAPI_HOST_PORT} 301 | NODE_IMAGES: ${NODE_IMAGES} 302 | restart: on-failure 303 | environment: 304 | TZ: Asia/Shanghai 305 | ports: 306 | - "${YAPI_HOST_PORT}:8005" 307 | #- "9090:9090" 308 | volumes: 309 | - ${YAPI_CONFIG_FILE}:/home/vendors/config.json:rw 310 | - ${YAPI_CONFIG_FILE}:/home/config.json:rw 311 | - ${YAPI_LOG_DIR}:/home/log 312 | depends_on: 313 | - mongodb 314 | cap_add: 315 | - SYS_PTRACE 316 | networks: 317 | - defNetworks 318 | 319 | ### drone ########## 320 | # 配置文档 https://docs.drone.io/server/overview/ 321 | drone: 322 | image: drone/drone:2 323 | volumes: 324 | - ./data/drone:/var/lib/drone/ 325 | - /var/run/docker.sock:/var/run/docker.sock 326 | environment: 327 | # 使用 gitlab,应用回调地址 {DRONE_SERVER_HOST}/login 328 | - DRONE_GITLAB=true 329 | - DRONE_GITLAB_CLIENT_ID=xxx 330 | - DRONE_GITLAB_CLIENT_SECRET=xxx 331 | - DRONE_GITLAB_SERVER=http://gitlab.xxx.com 332 | - DRONE_GITLAB_SKIP_VERIFY=true 333 | # 建议设置指定分组或用户,逗号分隔 334 | # - DRONE_USER_FILTER= 335 | # 输出日志 336 | - DRONE_LOGS_DEBUG=true 337 | - DRONE_OPEN=true 338 | # 访问域名或 IP 339 | - DRONE_SERVER_HOST=drone.xxx.com 340 | # https 还是 http 341 | - DRONE_SERVER_PROTO=https 342 | # Drone Server 和 Agent 的通信密钥,一个随机的长字符串 343 | - DRONE_RPC_SECRET=QWASFGTTG767TU4345435 344 | - DRONE_AGENTS_ENABLED=true 345 | networks: 346 | defNetworks: 347 | ipv4_address: 172.0.0.11 348 | depends_on: 349 | - drone-runner 350 | 351 | drone-runner: 352 | image: drone/drone-runner-docker:1.8 353 | volumes: 354 | - /var/run/docker.sock:/var/run/docker.sock 355 | environment: 356 | - DRONE_RPC_PROTO=http 357 | - DRONE_RPC_HOST=drone 358 | - DRONE_RPC_SECRET=QWASFGTTG767TU4345435 359 | - DRONE_RUNNER_CAPACITY=2 360 | - DRONE_RUNNER_NAME=drone-runner 361 | networks: 362 | - defNetworks 363 | 364 | ### monitor ########## 365 | grafana: 366 | image: ${GRAFANA_IMAGES} 367 | restart: on-failure 368 | ports: 369 | - "${GRAFANA_PORT}:3000" 370 | environment: 371 | TZ: Asia/Shanghai 372 | GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD} 373 | networks: 374 | - defNetworks 375 | depends_on: 376 | - prometheus 377 | - mysqlexporter 378 | volumes: 379 | - ${GRAFANA_CONFIG_FILE}:/etc/grafana/grafana.ini:ro 380 | - ${GRAFANA_LOG_DIR}:/var/log/grafana:rw 381 | - ${GRAFANA_DATA_DIR}:/var/lib/grafana:rw 382 | prometheus: 383 | image: ${PROM_IMAGES} 384 | restart: on-failure 385 | command: 386 | - "--config.file=/etc/prometheus/prometheus.yml" 387 | - "--storage.tsdb.path=/prometheus" 388 | environment: 389 | TZ: Asia/Shanghai 390 | networks: 391 | - defNetworks 392 | ports: 393 | - "${PROM_PORT}:9090" 394 | volumes: 395 | - ${PROM_CONFIG_FILE}:/etc/prometheus/prometheus.yml 396 | - ${PROM_DATA_DIR}:/prometheus 397 | mysqlexporter: 398 | image: prom/mysqld-exporter:v0.12.1 399 | networks: 400 | - defNetworks 401 | environment: 402 | - DATA_SOURCE_NAME=root:${MYSQL_ROOT_PASSWORD}@(mysql:3306)/ 403 | nodeexporter: 404 | image: prom/node-exporter:v1.0.1 405 | command: 406 | - "--path.rootfs=/host" 407 | networks: 408 | - defNetworks 409 | volumes: 410 | - "/:/host:ro,rslave" 411 | -------------------------------------------------------------------------------- /config/php/seccomp.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultAction": "SCMP_ACT_ERRNO", 3 | "archMap": [ 4 | { 5 | "architecture": "SCMP_ARCH_X86_64", 6 | "subArchitectures": [ 7 | "SCMP_ARCH_X86", 8 | "SCMP_ARCH_X32" 9 | ] 10 | }, 11 | { 12 | "architecture": "SCMP_ARCH_AARCH64", 13 | "subArchitectures": [ 14 | "SCMP_ARCH_ARM" 15 | ] 16 | }, 17 | { 18 | "architecture": "SCMP_ARCH_MIPS64", 19 | "subArchitectures": [ 20 | "SCMP_ARCH_MIPS", 21 | "SCMP_ARCH_MIPS64N32" 22 | ] 23 | }, 24 | { 25 | "architecture": "SCMP_ARCH_MIPS64N32", 26 | "subArchitectures": [ 27 | "SCMP_ARCH_MIPS", 28 | "SCMP_ARCH_MIPS64" 29 | ] 30 | }, 31 | { 32 | "architecture": "SCMP_ARCH_MIPSEL64", 33 | "subArchitectures": [ 34 | "SCMP_ARCH_MIPSEL", 35 | "SCMP_ARCH_MIPSEL64N32" 36 | ] 37 | }, 38 | { 39 | "architecture": "SCMP_ARCH_MIPSEL64N32", 40 | "subArchitectures": [ 41 | "SCMP_ARCH_MIPSEL", 42 | "SCMP_ARCH_MIPSEL64" 43 | ] 44 | }, 45 | { 46 | "architecture": "SCMP_ARCH_S390X", 47 | "subArchitectures": [ 48 | "SCMP_ARCH_S390" 49 | ] 50 | } 51 | ], 52 | "syscalls": [ 53 | { 54 | "names": [ 55 | "accept", 56 | "accept4", 57 | "access", 58 | "adjtimex", 59 | "alarm", 60 | "bind", 61 | "brk", 62 | "capget", 63 | "capset", 64 | "chdir", 65 | "chmod", 66 | "chown", 67 | "chown32", 68 | "clock_getres", 69 | "clock_gettime", 70 | "clock_nanosleep", 71 | "close", 72 | "connect", 73 | "copy_file_range", 74 | "creat", 75 | "dup", 76 | "dup2", 77 | "dup3", 78 | "epoll_create", 79 | "epoll_create1", 80 | "epoll_ctl", 81 | "epoll_ctl_old", 82 | "epoll_pwait", 83 | "epoll_wait", 84 | "epoll_wait_old", 85 | "eventfd", 86 | "eventfd2", 87 | "execve", 88 | "execveat", 89 | "exit", 90 | "exit_group", 91 | "faccessat", 92 | "fadvise64", 93 | "fadvise64_64", 94 | "fallocate", 95 | "fanotify_mark", 96 | "fchdir", 97 | "fchmod", 98 | "fchmodat", 99 | "fchown", 100 | "fchown32", 101 | "fchownat", 102 | "fcntl", 103 | "fcntl64", 104 | "fdatasync", 105 | "fgetxattr", 106 | "flistxattr", 107 | "flock", 108 | "fork", 109 | "fremovexattr", 110 | "fsetxattr", 111 | "fstat", 112 | "fstat64", 113 | "fstatat64", 114 | "fstatfs", 115 | "fstatfs64", 116 | "fsync", 117 | "ftruncate", 118 | "ftruncate64", 119 | "futex", 120 | "futimesat", 121 | "getcpu", 122 | "getcwd", 123 | "getdents", 124 | "getdents64", 125 | "getegid", 126 | "getegid32", 127 | "geteuid", 128 | "geteuid32", 129 | "getgid", 130 | "getgid32", 131 | "getgroups", 132 | "getgroups32", 133 | "getitimer", 134 | "getpeername", 135 | "getpgid", 136 | "getpgrp", 137 | "getpid", 138 | "getppid", 139 | "getpriority", 140 | "getrandom", 141 | "getresgid", 142 | "getresgid32", 143 | "getresuid", 144 | "getresuid32", 145 | "getrlimit", 146 | "get_robust_list", 147 | "getrusage", 148 | "getsid", 149 | "getsockname", 150 | "getsockopt", 151 | "get_thread_area", 152 | "gettid", 153 | "gettimeofday", 154 | "getuid", 155 | "getuid32", 156 | "getxattr", 157 | "inotify_add_watch", 158 | "inotify_init", 159 | "inotify_init1", 160 | "inotify_rm_watch", 161 | "io_cancel", 162 | "ioctl", 163 | "io_destroy", 164 | "io_getevents", 165 | "io_pgetevents", 166 | "ioprio_get", 167 | "ioprio_set", 168 | "io_setup", 169 | "io_submit", 170 | "io_uring_enter", 171 | "io_uring_register", 172 | "io_uring_setup", 173 | "ipc", 174 | "kill", 175 | "lchown", 176 | "lchown32", 177 | "lgetxattr", 178 | "link", 179 | "linkat", 180 | "listen", 181 | "listxattr", 182 | "llistxattr", 183 | "_llseek", 184 | "lremovexattr", 185 | "lseek", 186 | "lsetxattr", 187 | "lstat", 188 | "lstat64", 189 | "madvise", 190 | "memfd_create", 191 | "mincore", 192 | "mkdir", 193 | "mkdirat", 194 | "mknod", 195 | "mknodat", 196 | "mlock", 197 | "mlock2", 198 | "mlockall", 199 | "mmap", 200 | "mmap2", 201 | "mprotect", 202 | "mq_getsetattr", 203 | "mq_notify", 204 | "mq_open", 205 | "mq_timedreceive", 206 | "mq_timedsend", 207 | "mq_unlink", 208 | "mremap", 209 | "msgctl", 210 | "msgget", 211 | "msgrcv", 212 | "msgsnd", 213 | "msync", 214 | "munlock", 215 | "munlockall", 216 | "munmap", 217 | "nanosleep", 218 | "newfstatat", 219 | "_newselect", 220 | "open", 221 | "openat", 222 | "pause", 223 | "pipe", 224 | "pipe2", 225 | "poll", 226 | "ppoll", 227 | "prctl", 228 | "pread64", 229 | "preadv", 230 | "preadv2", 231 | "prlimit64", 232 | "pselect6", 233 | "pwrite64", 234 | "pwritev", 235 | "pwritev2", 236 | "read", 237 | "readahead", 238 | "readlink", 239 | "readlinkat", 240 | "readv", 241 | "recv", 242 | "recvfrom", 243 | "recvmmsg", 244 | "recvmsg", 245 | "remap_file_pages", 246 | "removexattr", 247 | "rename", 248 | "renameat", 249 | "renameat2", 250 | "restart_syscall", 251 | "rmdir", 252 | "rt_sigaction", 253 | "rt_sigpending", 254 | "rt_sigprocmask", 255 | "rt_sigqueueinfo", 256 | "rt_sigreturn", 257 | "rt_sigsuspend", 258 | "rt_sigtimedwait", 259 | "rt_tgsigqueueinfo", 260 | "sched_getaffinity", 261 | "sched_getattr", 262 | "sched_getparam", 263 | "sched_get_priority_max", 264 | "sched_get_priority_min", 265 | "sched_getscheduler", 266 | "sched_rr_get_interval", 267 | "sched_setaffinity", 268 | "sched_setattr", 269 | "sched_setparam", 270 | "sched_setscheduler", 271 | "sched_yield", 272 | "seccomp", 273 | "select", 274 | "semctl", 275 | "semget", 276 | "semop", 277 | "semtimedop", 278 | "send", 279 | "sendfile", 280 | "sendfile64", 281 | "sendmmsg", 282 | "sendmsg", 283 | "sendto", 284 | "setfsgid", 285 | "setfsgid32", 286 | "setfsuid", 287 | "setfsuid32", 288 | "setgid", 289 | "setgid32", 290 | "setgroups", 291 | "setgroups32", 292 | "setitimer", 293 | "setpgid", 294 | "setpriority", 295 | "setregid", 296 | "setregid32", 297 | "setresgid", 298 | "setresgid32", 299 | "setresuid", 300 | "setresuid32", 301 | "setreuid", 302 | "setreuid32", 303 | "setrlimit", 304 | "set_robust_list", 305 | "setsid", 306 | "setsockopt", 307 | "set_thread_area", 308 | "set_tid_address", 309 | "setuid", 310 | "setuid32", 311 | "setxattr", 312 | "shmat", 313 | "shmctl", 314 | "shmdt", 315 | "shmget", 316 | "shutdown", 317 | "sigaltstack", 318 | "signalfd", 319 | "signalfd4", 320 | "sigprocmask", 321 | "sigreturn", 322 | "socket", 323 | "socketcall", 324 | "socketpair", 325 | "splice", 326 | "stat", 327 | "stat64", 328 | "statfs", 329 | "statfs64", 330 | "statx", 331 | "symlink", 332 | "symlinkat", 333 | "sync", 334 | "sync_file_range", 335 | "syncfs", 336 | "sysinfo", 337 | "tee", 338 | "tgkill", 339 | "time", 340 | "timer_create", 341 | "timer_delete", 342 | "timerfd_create", 343 | "timerfd_gettime", 344 | "timerfd_settime", 345 | "timer_getoverrun", 346 | "timer_gettime", 347 | "timer_settime", 348 | "times", 349 | "tkill", 350 | "truncate", 351 | "truncate64", 352 | "ugetrlimit", 353 | "umask", 354 | "uname", 355 | "unlink", 356 | "unlinkat", 357 | "utime", 358 | "utimensat", 359 | "utimes", 360 | "vfork", 361 | "vmsplice", 362 | "wait4", 363 | "waitid", 364 | "waitpid", 365 | "write", 366 | "writev", 367 | "ptrace" 368 | ], 369 | "action": "SCMP_ACT_ALLOW", 370 | "args": [], 371 | "comment": "", 372 | "includes": {}, 373 | "excludes": {} 374 | }, 375 | { 376 | "names": [ 377 | "ptrace" 378 | ], 379 | "action": "SCMP_ACT_ALLOW", 380 | "args": null, 381 | "comment": "", 382 | "includes": { 383 | "minKernel": "4.8" 384 | }, 385 | "excludes": {} 386 | }, 387 | { 388 | "names": [ 389 | "personality" 390 | ], 391 | "action": "SCMP_ACT_ALLOW", 392 | "args": [ 393 | { 394 | "index": 0, 395 | "value": 0, 396 | "valueTwo": 0, 397 | "op": "SCMP_CMP_EQ" 398 | } 399 | ], 400 | "comment": "", 401 | "includes": {}, 402 | "excludes": {} 403 | }, 404 | { 405 | "names": [ 406 | "personality" 407 | ], 408 | "action": "SCMP_ACT_ALLOW", 409 | "args": [ 410 | { 411 | "index": 0, 412 | "value": 8, 413 | "valueTwo": 0, 414 | "op": "SCMP_CMP_EQ" 415 | } 416 | ], 417 | "comment": "", 418 | "includes": {}, 419 | "excludes": {} 420 | }, 421 | { 422 | "names": [ 423 | "personality" 424 | ], 425 | "action": "SCMP_ACT_ALLOW", 426 | "args": [ 427 | { 428 | "index": 0, 429 | "value": 131072, 430 | "valueTwo": 0, 431 | "op": "SCMP_CMP_EQ" 432 | } 433 | ], 434 | "comment": "", 435 | "includes": {}, 436 | "excludes": {} 437 | }, 438 | { 439 | "names": [ 440 | "personality" 441 | ], 442 | "action": "SCMP_ACT_ALLOW", 443 | "args": [ 444 | { 445 | "index": 0, 446 | "value": 131080, 447 | "valueTwo": 0, 448 | "op": "SCMP_CMP_EQ" 449 | } 450 | ], 451 | "comment": "", 452 | "includes": {}, 453 | "excludes": {} 454 | }, 455 | { 456 | "names": [ 457 | "personality" 458 | ], 459 | "action": "SCMP_ACT_ALLOW", 460 | "args": [ 461 | { 462 | "index": 0, 463 | "value": 4294967295, 464 | "valueTwo": 0, 465 | "op": "SCMP_CMP_EQ" 466 | } 467 | ], 468 | "comment": "", 469 | "includes": {}, 470 | "excludes": {} 471 | }, 472 | { 473 | "names": [ 474 | "sync_file_range2" 475 | ], 476 | "action": "SCMP_ACT_ALLOW", 477 | "args": [], 478 | "comment": "", 479 | "includes": { 480 | "arches": [ 481 | "ppc64le" 482 | ] 483 | }, 484 | "excludes": {} 485 | }, 486 | { 487 | "names": [ 488 | "arm_fadvise64_64", 489 | "arm_sync_file_range", 490 | "sync_file_range2", 491 | "breakpoint", 492 | "cacheflush", 493 | "set_tls" 494 | ], 495 | "action": "SCMP_ACT_ALLOW", 496 | "args": [], 497 | "comment": "", 498 | "includes": { 499 | "arches": [ 500 | "arm", 501 | "arm64" 502 | ] 503 | }, 504 | "excludes": {} 505 | }, 506 | { 507 | "names": [ 508 | "arch_prctl" 509 | ], 510 | "action": "SCMP_ACT_ALLOW", 511 | "args": [], 512 | "comment": "", 513 | "includes": { 514 | "arches": [ 515 | "amd64", 516 | "x32" 517 | ] 518 | }, 519 | "excludes": {} 520 | }, 521 | { 522 | "names": [ 523 | "modify_ldt" 524 | ], 525 | "action": "SCMP_ACT_ALLOW", 526 | "args": [], 527 | "comment": "", 528 | "includes": { 529 | "arches": [ 530 | "amd64", 531 | "x32", 532 | "x86" 533 | ] 534 | }, 535 | "excludes": {} 536 | }, 537 | { 538 | "names": [ 539 | "s390_pci_mmio_read", 540 | "s390_pci_mmio_write", 541 | "s390_runtime_instr" 542 | ], 543 | "action": "SCMP_ACT_ALLOW", 544 | "args": [], 545 | "comment": "", 546 | "includes": { 547 | "arches": [ 548 | "s390", 549 | "s390x" 550 | ] 551 | }, 552 | "excludes": {} 553 | }, 554 | { 555 | "names": [ 556 | "open_by_handle_at" 557 | ], 558 | "action": "SCMP_ACT_ALLOW", 559 | "args": [], 560 | "comment": "", 561 | "includes": { 562 | "caps": [ 563 | "CAP_DAC_READ_SEARCH" 564 | ] 565 | }, 566 | "excludes": {} 567 | }, 568 | { 569 | "names": [ 570 | "bpf", 571 | "clone", 572 | "fanotify_init", 573 | "lookup_dcookie", 574 | "mount", 575 | "name_to_handle_at", 576 | "perf_event_open", 577 | "quotactl", 578 | "setdomainname", 579 | "sethostname", 580 | "setns", 581 | "syslog", 582 | "umount", 583 | "umount2", 584 | "unshare" 585 | ], 586 | "action": "SCMP_ACT_ALLOW", 587 | "args": [], 588 | "comment": "", 589 | "includes": { 590 | "caps": [ 591 | "CAP_SYS_ADMIN" 592 | ] 593 | }, 594 | "excludes": {} 595 | }, 596 | { 597 | "names": [ 598 | "clone" 599 | ], 600 | "action": "SCMP_ACT_ALLOW", 601 | "args": [ 602 | { 603 | "index": 0, 604 | "value": 2114060288, 605 | "valueTwo": 0, 606 | "op": "SCMP_CMP_MASKED_EQ" 607 | } 608 | ], 609 | "comment": "", 610 | "includes": {}, 611 | "excludes": { 612 | "caps": [ 613 | "CAP_SYS_ADMIN" 614 | ], 615 | "arches": [ 616 | "s390", 617 | "s390x" 618 | ] 619 | } 620 | }, 621 | { 622 | "names": [ 623 | "clone" 624 | ], 625 | "action": "SCMP_ACT_ALLOW", 626 | "args": [ 627 | { 628 | "index": 1, 629 | "value": 2114060288, 630 | "valueTwo": 0, 631 | "op": "SCMP_CMP_MASKED_EQ" 632 | } 633 | ], 634 | "comment": "s390 parameter ordering for clone is different", 635 | "includes": { 636 | "arches": [ 637 | "s390", 638 | "s390x" 639 | ] 640 | }, 641 | "excludes": { 642 | "caps": [ 643 | "CAP_SYS_ADMIN" 644 | ] 645 | } 646 | }, 647 | { 648 | "names": [ 649 | "reboot" 650 | ], 651 | "action": "SCMP_ACT_ALLOW", 652 | "args": [], 653 | "comment": "", 654 | "includes": { 655 | "caps": [ 656 | "CAP_SYS_BOOT" 657 | ] 658 | }, 659 | "excludes": {} 660 | }, 661 | { 662 | "names": [ 663 | "chroot" 664 | ], 665 | "action": "SCMP_ACT_ALLOW", 666 | "args": [], 667 | "comment": "", 668 | "includes": { 669 | "caps": [ 670 | "CAP_SYS_CHROOT" 671 | ] 672 | }, 673 | "excludes": {} 674 | }, 675 | { 676 | "names": [ 677 | "delete_module", 678 | "init_module", 679 | "finit_module", 680 | "query_module" 681 | ], 682 | "action": "SCMP_ACT_ALLOW", 683 | "args": [], 684 | "comment": "", 685 | "includes": { 686 | "caps": [ 687 | "CAP_SYS_MODULE" 688 | ] 689 | }, 690 | "excludes": {} 691 | }, 692 | { 693 | "names": [ 694 | "acct" 695 | ], 696 | "action": "SCMP_ACT_ALLOW", 697 | "args": [], 698 | "comment": "", 699 | "includes": { 700 | "caps": [ 701 | "CAP_SYS_PACCT" 702 | ] 703 | }, 704 | "excludes": {} 705 | }, 706 | { 707 | "names": [ 708 | "kcmp", 709 | "process_vm_readv", 710 | "process_vm_writev", 711 | "ptrace" 712 | ], 713 | "action": "SCMP_ACT_ALLOW", 714 | "args": [], 715 | "comment": "", 716 | "includes": { 717 | "caps": [ 718 | "CAP_SYS_PTRACE" 719 | ] 720 | }, 721 | "excludes": {} 722 | }, 723 | { 724 | "names": [ 725 | "iopl", 726 | "ioperm" 727 | ], 728 | "action": "SCMP_ACT_ALLOW", 729 | "args": [], 730 | "comment": "", 731 | "includes": { 732 | "caps": [ 733 | "CAP_SYS_RAWIO" 734 | ] 735 | }, 736 | "excludes": {} 737 | }, 738 | { 739 | "names": [ 740 | "settimeofday", 741 | "stime", 742 | "clock_settime" 743 | ], 744 | "action": "SCMP_ACT_ALLOW", 745 | "args": [], 746 | "comment": "", 747 | "includes": { 748 | "caps": [ 749 | "CAP_SYS_TIME" 750 | ] 751 | }, 752 | "excludes": {} 753 | }, 754 | { 755 | "names": [ 756 | "vhangup" 757 | ], 758 | "action": "SCMP_ACT_ALLOW", 759 | "args": [], 760 | "comment": "", 761 | "includes": { 762 | "caps": [ 763 | "CAP_SYS_TTY_CONFIG" 764 | ] 765 | }, 766 | "excludes": {} 767 | }, 768 | { 769 | "names": [ 770 | "get_mempolicy", 771 | "mbind", 772 | "set_mempolicy" 773 | ], 774 | "action": "SCMP_ACT_ALLOW", 775 | "args": [], 776 | "comment": "", 777 | "includes": { 778 | "caps": [ 779 | "CAP_SYS_NICE" 780 | ] 781 | }, 782 | "excludes": {} 783 | }, 784 | { 785 | "names": [ 786 | "syslog" 787 | ], 788 | "action": "SCMP_ACT_ALLOW", 789 | "args": [], 790 | "comment": "", 791 | "includes": { 792 | "caps": [ 793 | "CAP_SYSLOG" 794 | ] 795 | }, 796 | "excludes": {} 797 | } 798 | ] 799 | } -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Service List: redis|mysql|mongodb|nginx|php|golang 4 | 5 | # Default Startup Service 6 | defaultContainer="nginx php mysql" 7 | # Default Service 8 | defaultBashContainer="php" 9 | 10 | mydir=$0 11 | _b=$(ls -ld $mydir | awk '{print $NF}') 12 | _c=$(ls -ld $mydir | awk '{print $(NF-2)}') 13 | [[ $_b =~ ^/ ]] && mydir=$_b || mydir=$(dirname $_c)/$_b 14 | 15 | WORK_DIR=$( 16 | cd $(dirname $mydir) 17 | pwd 18 | ) 19 | BIN_PATH="/usr/local/bin" 20 | WORK_NAME=${WORK_DIR##*/} 21 | SCRIPT_SOURCE_DIR=$(pwd) 22 | WHOAMI=$(whoami) 23 | TIME=$(date "+%Y-%m-%d %H:%M:%S") 24 | DATE=$(date "+%Y-%m-%d") 25 | cd $WORK_DIR 26 | 27 | [[ ! $PATH =~ $BIN_PATH ]] && export PATH=$PATH:$BIN_PATH 28 | 29 | function main() { 30 | if [[ ! -d $BIN_PATH ]]; then 31 | BIN_PATH="/usr/bin" 32 | fi 33 | local cmd 34 | config 35 | judge 36 | cmd=$1 37 | if [[ "" != $1 ]] && [[ "help" != $1 ]] && [[ "node" != $1 ]] && [[ "npm" != $1 ]] && [[ "sentry" != $1 ]] && [[ "go" != $1 ]] && [[ "composer" != $1 ]]; then 38 | shift 39 | fi 40 | case "$cmd" in 41 | status | s | ps) 42 | _status $@ 43 | ;; 44 | stop) 45 | _stop $@ 46 | ;; 47 | buildUp | buildup) 48 | _build $@ 49 | _start $@ 50 | ;; 51 | restart) 52 | _restart $@ 53 | ;; 54 | start | up) 55 | _start $@ 56 | ;; 57 | reload) 58 | _reload $@ 59 | ;; 60 | build) 61 | _build $@ 62 | ;; 63 | bash) 64 | _bash $@ 65 | ;; 66 | bash2) 67 | _bash2 $@ 68 | ;; 69 | cron) 70 | _cron $@ 71 | ;; 72 | php | composer) 73 | _php $@ 74 | ;; 75 | node | npm) 76 | _node $@ 77 | ;; 78 | go) 79 | _go $@ 80 | ;; 81 | sentry) 82 | _sentry $@ 83 | ;; 84 | stats) 85 | docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}" 86 | ;; 87 | ssl) 88 | _certbot $@ 89 | ;; 90 | ins) 91 | _inspect $@ 92 | ;; 93 | stop_all | stopAll | stopall) 94 | docker ps -a -q 95 | ;; 96 | delete_all | deleteAll | deleteall) 97 | docker system prune -a 98 | ;; 99 | tools) 100 | _tools 101 | ;; 102 | mysql) 103 | _mysqlTools $@ 104 | ;; 105 | mongodb) 106 | _mongodbTools $@ 107 | ;; 108 | installDocker | installdocker) 109 | _installDocker 110 | ;; 111 | help) 112 | _help $@ 113 | ;; 114 | logs) 115 | _logs $@ 116 | ;; 117 | name) 118 | echo $WORK_NAME 119 | ;; 120 | *) 121 | _help $@ 122 | ;; 123 | esac 124 | 125 | } 126 | 127 | function _help() { 128 | local cmd=${BASH_SOURCE[0]} 129 | cmd=$(echo $cmd | sed 's:\/usr\/bin\/::g') 130 | echo ' .__ .___ __ ' 131 | echo '________| | ______ __| _/ ____ ____ | | __ ____ _______ ' 132 | echo '\___ /| | / ___/ ______ / __ | / _ \ _/ ___\ | |/ /_/ __ \\_ __ \' 133 | echo ' / / | |__ \___ \ /_____/ / /_/ |( <_> )\ \___ | < \ ___/ | | \/' 134 | echo '/_____ \|____//____ > \____ | \____/ \___ >|__|_ \ \___ >|__| ' 135 | echo ' \/ \/ \/ \/ \/ \/ ' 136 | echo '' 137 | tips " $cmd start Start up service" 138 | tips " $cmd stop Stop of Service" 139 | tips " $cmd reload Reload Services" 140 | tips " $cmd restart Restart Services" 141 | tips " $cmd status View status" 142 | tips " $cmd stats Display resources used" 143 | tips " $cmd bash Exec Services" 144 | tips " $cmd cron Exec Crontab" 145 | tips " $cmd build Build services" 146 | tips " $cmd buildUp Build and start services" 147 | tips " $cmd tools Toolbox" 148 | tips " $cmd mysql Mysql operating" 149 | tips " $cmd ssl Renew the free certificates from Let's Encrypt." 150 | echo '' 151 | echo " Designated Language Directives(php, node, npm, golang, composer)" 152 | echo " $cmd php -v" 153 | echo " $cmd npm install xxx" 154 | echo ' ......' 155 | } 156 | 157 | function command_exists() { 158 | command -v "$1" 2>&1 159 | } 160 | 161 | function start_docker() { 162 | systemctl start docker && systemctl enable docker 163 | } 164 | 165 | function confirm() { 166 | echo -e -n "\033[34m$* \033[1;36m(Y/n)\033[0m" 167 | read -n 1 -s opt 168 | 169 | [[ "$opt" == $'\n' ]] || echo 170 | 171 | case "$opt" in 172 | 'y' | 'Y' ) return 0;; 173 | 'n' | 'N' ) return 1;; 174 | *) confirm "$1";; 175 | esac 176 | } 177 | 178 | function judge() { 179 | if [ -z `command_exists docker` ]; then 180 | tips "Missing Docker environment" 181 | if confirm "Do you need to install Docker automatically?"; then 182 | # askRoot 183 | curl -sSLk https://get.docker.com/ | bash 184 | if [ $? -ne "0" ]; then 185 | error "Docker installation failed" 186 | fi 187 | tips "Docker installation complete" 188 | else 189 | error "Abort installation" 190 | fi 191 | fi 192 | 193 | if [ -z `command_exists docker compose` ]; then 194 | if [ -z `command_exists docker-compose` ]; then 195 | tips "Docker-compose component not found" 196 | if confirm "Whether the Docker Compose Plugin needs to be installed automatically"; then 197 | curl -L https://github.com/docker/compose/releases/download/1.27.4/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose 198 | if [ $? -ne "0" ]; then 199 | error "Docker Compose Plugin installation failed" 200 | fi 201 | chmod +x /usr/local/bin/docker-compose 202 | tips "Docker Compose Plugin installation complete" 203 | else 204 | error "Abort installation" 205 | fi 206 | fi 207 | fi 208 | 209 | # type docker >/dev/null 2>&1 || { 210 | # _installDocker 211 | # error "Please install Docker!" 212 | # } 213 | 214 | # type docker-compose >/dev/null 2>&1 || { 215 | # tips "command:" 216 | # tips " sudo curl -L https://github.com/docker/compose/releases/download/1.27.4/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose" 217 | # tips " sudo chmod +x /usr/local/bin/docker-compose" 218 | # error "Please install docker-compose!" 219 | # } 220 | } 221 | 222 | function askRoot() { 223 | if [ $(id -u) != 0 ]; then 224 | error "You must be root to run this script, please use root run" 225 | fi 226 | } 227 | 228 | function config() { 229 | local dockerComposePath="$WORK_DIR/docker-compose.yml" 230 | local configPath="$WORK_DIR/.env" 231 | 232 | if [[ ! -f $configPath ]]; then 233 | cp $configPath".example" $configPath 234 | if [ $? -ne 0 ]; then 235 | error ".env does not exist, initialize Error." 236 | else 237 | tips ".env does not exist, initialize." 238 | fi 239 | fi 240 | 241 | if [[ ! -f $dockerComposePath ]]; then 242 | cp $dockerComposePath".example" $dockerComposePath 243 | if [ $? -ne 0 ]; then 244 | error "docker-compose.yml does not exist, initialize Error." 245 | else 246 | tips "docker-compose.yml does not exist, initialize." 247 | fi 248 | fi 249 | source $configPath 250 | } 251 | 252 | function _installDocker() { 253 | #askRoot 254 | 255 | local info=$(cat /etc/os-release) 256 | if [[ "" != $(echo $info | grep CentOS) ]]; then 257 | tips 'OS is CentOS' 258 | tips 'command:' 259 | tips " sudo curl -sSL https://get.docker.com | sh" 260 | tips " sudo usermod -aG docker $USER" 261 | tips " newgrp docker" 262 | tips " sudo curl -L https://github.com/docker/compose/releases/download/1.27.4/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose" 263 | tips " sudo chmod +x /usr/local/bin/docker-compose" 264 | tips " docker-compose --version" 265 | tips "start: " 266 | tips " sudo systemctl start docker" 267 | tips " sudo systemctl enable docker" 268 | elif [[ "" != $(echo $info | grep Ubuntu) ]]; then 269 | tips 'OS is Ubuntu' 270 | tips 'command:' 271 | tips " sudo curl -sSL https://get.docker.com | sh" 272 | tips " sudo usermod -aG docker $USER" 273 | tips " newgrp docker" 274 | tips " sudo curl -L https://github.com/docker/compose/releases/download/1.27.4/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose" 275 | tips " sudo chmod +x /usr/local/bin/docker-compose" 276 | tips " docker-compose --version" 277 | tips "start: " 278 | tips " sudo service start docker" 279 | else 280 | tips "See: https://docs.docker.com/install/" 281 | fi 282 | } 283 | 284 | function _install() { 285 | local zdc="$BIN_PATH/zdc" 286 | local zdocker="$BIN_PATH/zdocker" 287 | if [ -f "$zdocker" ]; then 288 | sudo mv -f $zdocker $zdocker"-old" 289 | fi 290 | 291 | if [ -f "$zdc" ]; then 292 | tips "old zdc mv zdc-old" 293 | sudo mv -f $zdc $zdc"-old" 294 | fi 295 | 296 | sudo ln -s $WORK_DIR/run.sh $zdocker 297 | sudo ln -s $WORK_DIR/run.sh $zdc 298 | tips "You can now use zdc instead of ./run.sh: " 299 | tips " zdc up" 300 | tips " zdc help" 301 | } 302 | 303 | function _tools() { 304 | tips "********please enter your choise:(1-7)****" 305 | cat <&2 498 | exit 1 499 | } 500 | 501 | function _php() { 502 | local phpv="php" 503 | local cmd 504 | cmd=$1 505 | images $phpv 506 | local composerPath=$( 507 | cd ${COMPOSER_DATA_DIR/.\/$SCRIPT_SOURCE_DIR/} 508 | pwd 509 | ) 510 | if [[ "composer" == $cmd ]]; then 511 | docker run --tty --interactive --rm --cap-add SYS_PTRACE --volume $composerPath:/composer:rw --volume $SCRIPT_SOURCE_DIR:/var/www/html --workdir /var/www/html $WORK_NAME"_php" $@ 512 | 513 | #docker run --tty --interactive --rm --user $(id -u):$(id -g) --cap-add SYS_PTRACE --volume /etc/passwd:/etc/passwd:ro --volume /etc/group:/etc/group:ro --volume $composerPath:/composer:rw --volume $SCRIPT_SOURCE_DIR:/var/www/html --workdir /var/www/html $WORK_NAME"_php" $@ 514 | else 515 | # _bash $phpv php $@ 516 | docker run --tty --interactive --rm --cap-add SYS_PTRACE --volume $composerPath:/composer:rw --volume $SCRIPT_SOURCE_DIR:/var/www/html --workdir /var/www/html $WORK_NAME"_php" php $@ 517 | fi 518 | } 519 | 520 | function _sentry() { 521 | images sentry 522 | _bash sentry "$@" 523 | } 524 | 525 | function _node() { 526 | images node 527 | docker run --tty --interactive --rm --volume $SCRIPT_SOURCE_DIR:/var/www/html:rw --workdir /var/www/html $WORK_NAME"_node" "$@" 528 | } 529 | 530 | function _go() { 531 | images go 532 | local goproxy=https://goproxy.cn,direct 533 | if [[ -n "${GOPROXY}" ]]; then 534 | goproxy=$GOPROXY 535 | fi 536 | local cmd=$@ 537 | if [[ "bash" == $2 ]];then 538 | docker run -it -e GOPROXY="$goproxy" --volume $SCRIPT_SOURCE_DIR:/var/www/html:rw --workdir /var/www/html $WORK_NAME"_go" bash 539 | return 540 | fi 541 | if [[ -n "${GOPROXY}" ]]; then 542 | docker run --tty --interactive -e GOPROXY="$goproxy" --volume $SCRIPT_SOURCE_DIR:/var/www/html:rw --workdir /var/www/html $WORK_NAME"_go" "$cmd" 543 | fi 544 | } 545 | 546 | function images() { 547 | local container=$1 548 | if [[ "" == $(echo $(docker images) | grep $WORK_NAME"_"$container) ]]; then 549 | tips "The $container service is for the first time, please wait ..." 550 | _start --build $container 551 | elif [[ "" == $(echo $(compose images) | grep $WORK_NAME"_"$container) ]]; then 552 | _start $container 553 | fi 554 | } 555 | 556 | function compose() { 557 | if [ -z `command_exists "docker-compose"` ]; then 558 | docker compose $@ 559 | elif [ -z `command_exists "docker compose"` ]; then 560 | docker-compose $@ 561 | fi 562 | } 563 | 564 | function __path() { 565 | echo $1 566 | } 567 | 568 | function _logs() { 569 | local container=$1 570 | compose logs $container 571 | } 572 | 573 | function _certbot() { 574 | local certsPath="$WORK_DIR" 575 | local ACME=~/.acme.sh/acme.sh 576 | local binCmd=$certsPath/run.sh 577 | local zdc="$BIN_PATH/zdc" 578 | if [ -f "$zdc" ]; then 579 | binCmd=zdc 580 | fi 581 | local help="Usage: $binCmd ssl -d mydomain.com -w $certsPath/www/mydomain.com/public" 582 | local email 583 | local debug 584 | local force 585 | local reloadcmd 586 | if [ ! -f "$ACME" ]; then 587 | tips "$ACME does not exist, installing..." 588 | curl https://get.acme.sh | sh 589 | # 自动更新 590 | $ACME --upgrade --auto-upgrade 591 | #tips "Please set a scheduled task:" 592 | #echo -e " 55 5 * * * $cmd reload" 593 | fi 594 | 595 | if [[ "$1" == "" ]]; then 596 | error $help 597 | fi 598 | 599 | args=() 600 | 601 | while [ "$1" != "" ]; do 602 | case "$1" in 603 | --email ) email="$2"; shift;; 604 | --dns ) dns="$2"; shift;; 605 | -d | --domain ) domain="$2"; shift;; 606 | -B | --broad ) broad="general analysis"; shift;; 607 | -B | --broad ) broad="general analysis"; shift;; 608 | -a | --alias ) alias="$2"; shift;; 609 | -w | --webroot ) webroot="--webroot $2"; shift;; 610 | -h | --help ) tips $help; exit;; 611 | * ) args+=("$1") 612 | esac 613 | shift 614 | done 615 | if [[ -z "${domain}" ]]; then 616 | error "Please enter the domain name" 617 | fi 618 | 619 | 620 | if [[ -z ${webroot} && -n "${dns}" ]]; then 621 | # dns_cf 622 | dns="--dns ${dns}"; 623 | fi 624 | 625 | if [[ -n "${broad}" ]]; then 626 | broad="-d *.${domain}"; 627 | fi 628 | 629 | if [[ -n "${alias}" ]]; then 630 | alias_str="--challenge-alias ${alias}"; 631 | fi 632 | 633 | ## --force --debug --reloadcmd "zdc reload" 634 | 635 | $ACME --issue $dns $alias_str -d $domain $broad $webroot $args 636 | 637 | if [ $? -ne 0 ]; then 638 | exit 639 | fi 640 | 641 | echo "create certs dir: $certsPath/config/nginx/conf.d/certs/$domain" 642 | mkdir -p $certsPath/config/nginx/conf.d/certs/$domain 643 | 644 | $ACME --install-cert -d $domain $broad --reloadcmd "${binCmd} reload" --key-file $certsPath/config/nginx/conf.d/certs/$domain/server.key --fullchain-file $certsPath/config/nginx/conf.d/certs/$domain/server.crt 645 | 646 | tips "reference:" 647 | echo " cp $certsPath/config/nginx/conf.d/localhost_https.conf $certsPath/config/nginx/conf.d/[DOMAIN]_https.conf" 648 | } 649 | 650 | function _mysqlTools() { 651 | local yes=0 652 | local BAK_DIR="$MYSQL_CONF_DIR/backup" 653 | local BAK_FILE="$BAK_DIR/$TIME.sql" 654 | local DAYS=15 655 | mkdir -p $BAK_DIR 656 | if [[ "backup" == $1 ]]; then 657 | cat >$BAK_DIR/.bak_mysql.sh< "/mysql/backup/${TIME}.sql" 661 | 662 | find /mysql/backup/ -mtime +$DAYS -delete 663 | EOF 664 | _bash mysql chmod 777 /mysql/backup/.bak_mysql.sh 665 | _bash mysql /mysql/backup/.bak_mysql.sh 666 | if [ $? -eq 0 ];then 667 | echo "bak database Sucessfully." 668 | echo "export -> $BAK_FILE" 669 | else 670 | echo "bak database failed!" 671 | echo $(pwd) 672 | echo $BAK_DIR 673 | cat $BAK_DIR/.bak_mysql.sh 674 | fi 675 | rm -f $BAK_DIR/.bak_mysql.sh 676 | exit 677 | fi 678 | tips "********Mysql Tools****" 679 | cat < "$BAK_FILE" 692 | echo "export -> $BAK_FILE" 693 | else 694 | echo "Give up Export mysql" 695 | fi 696 | ;; 697 | 2) 698 | tips 'command:' 699 | echo " ${BASH_SOURCE[0]} bash mysql" 700 | echo " mysql -uroot -p$MYSQL_ROOT_PASSWORD" 701 | echo " source /mysql/backup/xxx.sql" 702 | ;; 703 | 3) 704 | __Enter_Database_Name 705 | tips "Please enter password for mysql user ${database_name}: " 706 | read mysql_password 707 | echo "Your password: ${mysql_password} " 708 | cat >$BAK_DIR/.add_mysql.sql<$BAK_DIR/.add_mysql.sh<$BAK_DIR/.bak.sh< $BAK_FILE" 760 | else 761 | echo "bak database failed!" 762 | echo $(pwd) 763 | echo $BAK_DIR 764 | cat $BAK_DIR/.bak.sh 765 | fi 766 | rm -f $BAK_DIR/.bak.sh 767 | exit 768 | fi 769 | } 770 | 771 | function __Enter_Database_Name() 772 | { 773 | while :;do 774 | tips "Enter database name: " 775 | read database_name 776 | if [ "${database_name}" == "" ]; then 777 | error "Database Name can't be empty!" 778 | else 779 | break 780 | fi 781 | done 782 | } 783 | 784 | function __determine() { 785 | echo -e "Please determine if you want to perform \033[32m$1\033[0m operation (yes|NO)" 786 | read -p "Now select the top option to: " input 787 | case $input in 788 | "y" | "Y" | "yes" | "YES") 789 | return 1 790 | ;; 791 | *) 792 | return 0 793 | ;; 794 | esac 795 | } 796 | 797 | function _inspect() { 798 | docker inspect $WORK_NAME"_$@" 799 | } 800 | 801 | function __yapi() { 802 | compose up -d yapi 803 | tips "yapi: http://127.0.0.1:$YAPI_HOST_PORT" 804 | } 805 | 806 | function __sentry() { 807 | local cmd=${BASH_SOURCE[0]} 808 | # shellcheck disable=SC2001 809 | cmd=$(echo $cmd | sed 's:\/usr\/bin\/::g') 810 | compose up -d sentry sentry_celery_beat sentry_celery_worker 811 | tips "For the first time, please execute the following command to initialize sentry:\n" 812 | tips " $cmd sentry upgrade" 813 | tips "" 814 | } 815 | 816 | main "$@" 817 | -------------------------------------------------------------------------------- /config/grafana/grafana.ini: -------------------------------------------------------------------------------- 1 | ##################### Grafana Configuration Example ##################### 2 | # 3 | # Everything has defaults so you only need to uncomment things you want to 4 | # change 5 | 6 | # possible values : production, development 7 | ;app_mode = production 8 | 9 | # instance name, defaults to HOSTNAME environment variable value or hostname if HOSTNAME var is empty 10 | ;instance_name = ${HOSTNAME} 11 | 12 | #################################### Paths #################################### 13 | [paths] 14 | # Path to where grafana can store temp files, sessions, and the sqlite3 db (if that is used) 15 | ;data = /var/lib/grafana 16 | 17 | # Temporary files in `data` directory older than given duration will be removed 18 | ;temp_data_lifetime = 24h 19 | 20 | # Directory where grafana can store logs 21 | ;logs = /var/log/grafana 22 | 23 | # Directory where grafana will automatically scan and look for plugins 24 | ;plugins = /var/lib/grafana/plugins 25 | 26 | # folder that contains provisioning config files that grafana will apply on startup and while running. 27 | ;provisioning = conf/provisioning 28 | 29 | #################################### Server #################################### 30 | [server] 31 | # Protocol (http, https, h2, socket) 32 | ;protocol = http 33 | 34 | # The ip address to bind to, empty will bind to all interfaces 35 | ;http_addr = 36 | 37 | # The http port to use 38 | ;http_port = 3000 39 | 40 | # The public facing domain name used to access grafana from a browser 41 | ;domain = localhost 42 | 43 | # Redirect to correct domain if host header does not match domain 44 | # Prevents DNS rebinding attacks 45 | ;enforce_domain = false 46 | 47 | # The full public facing url you use in browser, used for redirects and emails 48 | # If you use reverse proxy and sub path specify full url (with sub path) 49 | ;root_url = %(protocol)s://%(domain)s:%(http_port)s/ 50 | 51 | # Serve Grafana from subpath specified in `root_url` setting. By default it is set to `false` for compatibility reasons. 52 | ;serve_from_sub_path = false 53 | 54 | # Log web requests 55 | ;router_logging = false 56 | 57 | # the path relative working path 58 | ;static_root_path = public 59 | 60 | # enable gzip 61 | ;enable_gzip = false 62 | 63 | # https certs & key file 64 | ;cert_file = 65 | ;cert_key = 66 | 67 | # Unix socket path 68 | ;socket = 69 | 70 | #################################### Database #################################### 71 | [database] 72 | # You can configure the database connection by specifying type, host, name, user and password 73 | # as separate properties or as on string using the url properties. 74 | 75 | # Either "mysql", "postgres" or "sqlite3", it's your choice 76 | ;type = sqlite3 77 | ;host = 127.0.0.1:3306 78 | ;name = grafana 79 | ;user = root 80 | # If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;""" 81 | ;password = 82 | 83 | # Use either URL or the previous fields to configure the database 84 | # Example: mysql://user:secret@host:port/database 85 | ;url = 86 | 87 | # For "postgres" only, either "disable", "require" or "verify-full" 88 | ;ssl_mode = disable 89 | 90 | ;ca_cert_path = 91 | ;client_key_path = 92 | ;client_cert_path = 93 | ;server_cert_name = 94 | 95 | # For "sqlite3" only, path relative to data_path setting 96 | ;path = grafana.db 97 | 98 | # Max idle conn setting default is 2 99 | ;max_idle_conn = 2 100 | 101 | # Max conn setting default is 0 (mean not set) 102 | ;max_open_conn = 103 | 104 | # Connection Max Lifetime default is 14400 (means 14400 seconds or 4 hours) 105 | ;conn_max_lifetime = 14400 106 | 107 | # Set to true to log the sql calls and execution times. 108 | ;log_queries = 109 | 110 | # For "sqlite3" only. cache mode setting used for connecting to the database. (private, shared) 111 | ;cache_mode = private 112 | 113 | #################################### Cache server ############################# 114 | [remote_cache] 115 | # Either "redis", "memcached" or "database" default is "database" 116 | ;type = database 117 | 118 | # cache connectionstring options 119 | # database: will use Grafana primary database. 120 | # redis: config like redis server e.g. `addr=127.0.0.1:6379,pool_size=100,db=0,ssl=false`. Only addr is required. ssl may be 'true', 'false', or 'insecure'. 121 | # memcache: 127.0.0.1:11211 122 | ;connstr = 123 | 124 | #################################### Data proxy ########################### 125 | [dataproxy] 126 | 127 | # This enables data proxy logging, default is false 128 | ;logging = false 129 | 130 | # How long the data proxy waits before timing out, default is 30 seconds. 131 | # This setting also applies to core backend HTTP data sources where query requests use an HTTP client with timeout set. 132 | ;timeout = 30 133 | 134 | # How many seconds the data proxy waits before sending a keepalive probe request. 135 | ;keep_alive_seconds = 30 136 | 137 | # How many seconds the data proxy waits for a successful TLS Handshake before timing out. 138 | ;tls_handshake_timeout_seconds = 10 139 | 140 | # How many seconds the data proxy will wait for a server's first response headers after 141 | # fully writing the request headers if the request has an "Expect: 100-continue" 142 | # header. A value of 0 will result in the body being sent immediately, without 143 | # waiting for the server to approve. 144 | ;expect_continue_timeout_seconds = 1 145 | 146 | # The maximum number of idle connections that Grafana will keep alive. 147 | ;max_idle_connections = 100 148 | 149 | # How many seconds the data proxy keeps an idle connection open before timing out. 150 | ;idle_conn_timeout_seconds = 90 151 | 152 | # If enabled and user is not anonymous, data proxy will add X-Grafana-User header with username into the request, default is false. 153 | ;send_user_header = false 154 | 155 | #################################### Analytics #################################### 156 | [analytics] 157 | # Server reporting, sends usage counters to stats.grafana.org every 24 hours. 158 | # No ip addresses are being tracked, only simple counters to track 159 | # running instances, dashboard and error counts. It is very helpful to us. 160 | # Change this option to false to disable reporting. 161 | ;reporting_enabled = true 162 | 163 | # Set to false to disable all checks to https://grafana.net 164 | # for new versions (grafana itself and plugins), check is used 165 | # in some UI views to notify that grafana or plugin update exists 166 | # This option does not cause any auto updates, nor send any information 167 | # only a GET request to http://grafana.com to get latest versions 168 | ;check_for_updates = true 169 | 170 | # Google Analytics universal tracking code, only enabled if you specify an id here 171 | ;google_analytics_ua_id = 172 | 173 | # Google Tag Manager ID, only enabled if you specify an id here 174 | ;google_tag_manager_id = 175 | 176 | #################################### Security #################################### 177 | [security] 178 | # disable creation of admin user on first start of grafana 179 | ;disable_initial_admin_creation = false 180 | 181 | # default admin user, created on startup 182 | ;admin_user = admin 183 | 184 | # default admin password, can be changed before first start of grafana, or in profile settings 185 | ;admin_password = admin 186 | 187 | # used for signing 188 | ;secret_key = SW2YcwTIb9zpOOhoPsMm 189 | 190 | # disable gravatar profile images 191 | ;disable_gravatar = false 192 | 193 | # data source proxy whitelist (ip_or_domain:port separated by spaces) 194 | ;data_source_proxy_whitelist = 195 | 196 | # disable protection against brute force login attempts 197 | ;disable_brute_force_login_protection = false 198 | 199 | # set to true if you host Grafana behind HTTPS. default is false. 200 | ;cookie_secure = false 201 | 202 | # set cookie SameSite attribute. defaults to `lax`. can be set to "lax", "strict", "none" and "disabled" 203 | ;cookie_samesite = lax 204 | 205 | # set to true if you want to allow browsers to render Grafana in a ,