Refactor to deploy Heroku using new Docker image (#9127)

This commit is contained in:
geekup-legodevops 2022-03-24 14:47:36 +07:00 committed by GitHub
parent 6c3116b0aa
commit 382ea53ab3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 112 additions and 216 deletions

View File

@ -91,6 +91,5 @@ ENV PATH /opt/appsmith/utils/node_modules/.bin:$PATH
EXPOSE 80 EXPOSE 80
EXPOSE 443 EXPOSE 443
EXPOSE 9001
ENTRYPOINT [ "/opt/appsmith/entrypoint.sh" ] ENTRYPOINT [ "/opt/appsmith/entrypoint.sh" ]
CMD ["/usr/bin/supervisord", "-n"] CMD ["/usr/bin/supervisord", "-n"]

View File

@ -36,6 +36,10 @@
"APPSMITH_DISABLE_TELEMETRY": { "APPSMITH_DISABLE_TELEMETRY": {
"description" : "We want to be transparent and request that you share anonymous usage data with us. This data is purely statistical in nature and helps us understand your needs & provide better support to your self-hosted instance. You can read more about what information is collected in our documentation https://docs.appsmith.com/v/v1.2.1/setup/telemetry", "description" : "We want to be transparent and request that you share anonymous usage data with us. This data is purely statistical in nature and helps us understand your needs & provide better support to your self-hosted instance. You can read more about what information is collected in our documentation https://docs.appsmith.com/v/v1.2.1/setup/telemetry",
"value": "false" "value": "false"
},
"APPSMITH_SUPERVISOR_PASSWORD": {
"description": "Basic authentication password to access Supervisor UI - An web interface, which allow you to manage various process",
"value": ""
} }
} }
} }

View File

@ -164,7 +164,7 @@ This command will migrate all data and configuration of running container on sou
The container runs multiple processes, including the Appsmith server, Nginx, MongoDB etc., inside a single Docker container. These processes are started and managed by [supervisord](http://supervisord.org/). The container runs multiple processes, including the Appsmith server, Nginx, MongoDB etc., inside a single Docker container. These processes are started and managed by [supervisord](http://supervisord.org/).
Supervisord comes with a web interface for managing the various processes, available at <http://localhost:9001>, as well as a command line interface towards the same goal. Supervisord comes with a web interface for managing the various processes, available at <http://localhost/supervisor/>, as well as a command line interface towards the same goal.
Here's a screenshot of the web interface listing all the processes managed: Here's a screenshot of the web interface listing all the processes managed:

View File

@ -9,7 +9,6 @@ services:
ports: ports:
- "80:80" - "80:80"
- "443:443" - "443:443"
- "9001:9001"
volumes: volumes:
- ./stacks:/appsmith-stacks - ./stacks:/appsmith-stacks

View File

@ -2,6 +2,22 @@
set -e set -e
function get_maximum_heap(){
resource=$(ulimit -u)
echo "Resource : $resource"
if [[ "$resource" -le 256 ]]; then
maximum_heap=128
elif [[ "$resource" -le 512 ]]; then
maximum_heap=256
fi
}
function setup_backend_heap_arg(){
if [[ ! -z ${maximum_heap} ]]; then
export APPSMITH_JAVA_HEAP_ARG="-Xmx${maximum_heap}m"
fi
}
init_env_file() { init_env_file() {
CONF_PATH="/appsmith-stacks/configuration" CONF_PATH="/appsmith-stacks/configuration"
ENV_PATH="$CONF_PATH/docker.env" ENV_PATH="$CONF_PATH/docker.env"
@ -24,7 +40,11 @@ init_env_file() {
tr -dc A-Za-z0-9 </dev/urandom | head -c 13 tr -dc A-Za-z0-9 </dev/urandom | head -c 13
echo "" echo ""
) )
bash "$TEMPLATES_PATH/docker.env.sh" "$APPSMITH_MONGODB_USER" "$APPSMITH_MONGODB_PASSWORD" "$APPSMITH_ENCRYPTION_PASSWORD" "$APPSMITH_ENCRYPTION_SALT" > "$ENV_PATH" APPSMITH_AUTH_PASSWORD=$(
tr -dc A-Za-z0-9 </dev/urandom | head -c 13
echo ''
)
bash "$TEMPLATES_PATH/docker.env.sh" "$APPSMITH_MONGODB_USER" "$APPSMITH_MONGODB_PASSWORD" "$APPSMITH_ENCRYPTION_PASSWORD" "$APPSMITH_ENCRYPTION_SALT" "$APPSMITH_AUTH_PASSWORD" > "$ENV_PATH"
fi fi
# Build an env file with current env variables. We single-quote the values, as well as escaping any single-quote characters. # Build an env file with current env variables. We single-quote the values, as well as escaping any single-quote characters.
@ -159,6 +179,7 @@ configure_supervisord() {
cp -f "$SUPERVISORD_CONF_PATH/application_process/"*.conf /etc/supervisor/conf.d cp -f "$SUPERVISORD_CONF_PATH/application_process/"*.conf /etc/supervisor/conf.d
# Disable services based on configuration # Disable services based on configuration
if [[ -z "${DYNO}" ]]; then
if [[ $isUriLocal -eq 0 ]]; then if [[ $isUriLocal -eq 0 ]]; then
cp "$SUPERVISORD_CONF_PATH/mongodb.conf" /etc/supervisor/conf.d/ cp "$SUPERVISORD_CONF_PATH/mongodb.conf" /etc/supervisor/conf.d/
fi fi
@ -170,17 +191,29 @@ configure_supervisord() {
if ! [[ -e "/appsmith-stacks/ssl/fullchain.pem" ]] || ! [[ -e "/appsmith-stacks/ssl/privkey.pem" ]]; then if ! [[ -e "/appsmith-stacks/ssl/fullchain.pem" ]] || ! [[ -e "/appsmith-stacks/ssl/privkey.pem" ]]; then
cp "$SUPERVISORD_CONF_PATH/cron.conf" /etc/supervisor/conf.d/ cp "$SUPERVISORD_CONF_PATH/cron.conf" /etc/supervisor/conf.d/
fi fi
fi
} }
# Main Section # Main Section
init_env_file init_env_file
unset_unused_variables unset_unused_variables
check_mongodb_uri check_mongodb_uri
if [[ -z "${DYNO}" ]]; then
# Don't run MongoDB if running in a Heroku dyno.
init_mongodb init_mongodb
init_replica_set init_replica_set
fi
mount_letsencrypt_directory mount_letsencrypt_directory
# These functions are used to limit heap size for Backend process when deployed on Heroku
get_maximum_heap
setup_backend_heap_arg
configure_supervisord configure_supervisord
CREDENTIAL_PATH="/etc/nginx/passwords"
if ! [[ -e "$CREDENTIAL_PATH" ]]; then
echo "Generating Basic Authentication file"
printf "$APPSMITH_SUPERVISOR_USER:$(openssl passwd -apr1 $APPSMITH_SUPERVISOR_PASSWORD)" > "$CREDENTIAL_PATH"
fi
# Ensure the restore path exists in the container, so an archive can be copied to it, if need be. # Ensure the restore path exists in the container, so an archive can be copied to it, if need be.
mkdir -p /appsmith-stacks/data/{backup,restore} mkdir -p /appsmith-stacks/data/{backup,restore}

View File

@ -1,4 +1,4 @@
#!/bin/bash #!/bin/bash
# Ref -Dlog4j2.formatMsgNoLookups=true https://spring.io/blog/2021/12/10/log4j2-vulnerability-and-spring-boot # Ref -Dlog4j2.formatMsgNoLookups=true https://spring.io/blog/2021/12/10/log4j2-vulnerability-and-spring-boot
exec java ${APPSMITH_JAVA_ARGS:-} -Dserver.port=8080 -Djava.security.egd=file:/dev/./urandom -Dlog4j2.formatMsgNoLookups=true -jar server.jar exec java ${APPSMITH_JAVA_ARGS:-} ${APPSMITH_JAVA_HEAP_ARG:-} -Dserver.port=8080 -Djava.security.egd=file:/dev/./urandom -Dlog4j2.formatMsgNoLookups=true -jar server.jar

View File

@ -40,10 +40,12 @@ ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
EOF EOF
# Check exist certificate with given custom domain # Check exist certificate with given custom domain
if [[ -n ${APPSMITH_CUSTOM_DOMAIN:-} ]]; then # Heroku not support for custom domain, only generate HTTP config if deploying on Heroku
if [[ -n $APPSMITH_CUSTOM_DOMAIN ]] && [[ -z $DYNO ]]; then
APP_TEMPLATE="$https_conf" APP_TEMPLATE="$https_conf"
if ! [[ -e "/etc/letsencrypt/live/$APPSMITH_CUSTOM_DOMAIN" ]]; then if ! [[ -e "/etc/letsencrypt/live/$APPSMITH_CUSTOM_DOMAIN" ]]; then
source "/opt/appsmith/init_ssl_cert.sh" source "/opt/appsmith/init_ssl_cert.sh"
init_ssl_cert "$APPSMITH_CUSTOM_DOMAIN"
if ! init_ssl_cert "$APPSMITH_CUSTOM_DOMAIN"; then if ! init_ssl_cert "$APPSMITH_CUSTOM_DOMAIN"; then
echo "Status code from init_ssl_cert is $?" echo "Status code from init_ssl_cert is $?"
APP_TEMPLATE="$http_conf" APP_TEMPLATE="$http_conf"

View File

@ -5,6 +5,7 @@ MONGO_USER="$1"
MONGO_PASSWORD="$2" MONGO_PASSWORD="$2"
ENCRYPTION_PASSWORD="$3" ENCRYPTION_PASSWORD="$3"
ENCRYPTION_SALT="$4" ENCRYPTION_SALT="$4"
BASIC_AUTH_PASSWORD="$4"
cat <<EOF cat <<EOF
# Sentry # Sentry
@ -88,4 +89,6 @@ APPSMITH_JAVA_ARGS=
# MAX PAYLOAD SIZE # MAX PAYLOAD SIZE
# APPSMITH_CODEC_SIZE= # APPSMITH_CODEC_SIZE=
APPSMITH_SUPERVISOR_USER=appsmith
APPSMITH_SUPERVISOR_PASSWORD=$BASIC_AUTH_PASSWORD
EOF EOF

View File

@ -15,7 +15,7 @@ map \$http_x_forwarded_proto \$origin_scheme {
} }
server { server {
listen 80; listen ${PORT:-80} default_server;
server_name $CUSTOM_DOMAIN; server_name $CUSTOM_DOMAIN;
client_max_body_size 100m; client_max_body_size 100m;
@ -29,6 +29,28 @@ server {
root /appsmith-stacks/data/certificate/certbot; root /appsmith-stacks/data/certificate/certbot;
} }
location = /supervisor {
return 301 /supervisor/;
}
location /supervisor/ {
proxy_http_version 1.1;
proxy_buffering off;
proxy_max_temp_file_size 0;
proxy_redirect off;
proxy_set_header Host \$http_host/supervisor/;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_set_header X-Forwarded-Host \$http_host;
proxy_set_header Connection "";
proxy_pass http://localhost:9001/;
auth_basic "Protected";
auth_basic_user_file /etc/nginx/passwords;
}
proxy_set_header X-Forwarded-Proto \$origin_scheme; proxy_set_header X-Forwarded-Proto \$origin_scheme;
proxy_set_header X-Forwarded-Host \$host; proxy_set_header X-Forwarded-Host \$host;

View File

@ -34,10 +34,32 @@ server {
ssl_certificate $SSL_CERT_PATH; ssl_certificate $SSL_CERT_PATH;
ssl_certificate_key $SSL_KEY_PATH; ssl_certificate_key $SSL_KEY_PATH;
include /appsmith-stacks/data/certificate/conf/options-ssl-nginx.conf; include /appsmith-stacks/data/certificate/conf/options-ssl-nginx.conf;
ssl_dhparam /appsmith-stacks/data/certificate/conf/ssl-dhparams.pem; ssl_dhparam /appsmith-stacks/data/certificate/conf/ssl-dhparams.pem;
location = /supervisor {
return 301 /supervisor/;
}
location /supervisor/ {
proxy_http_version 1.1;
proxy_buffering off;
proxy_max_temp_file_size 0;
proxy_redirect off;
proxy_set_header Host \$http_host/supervisor/;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$origin_scheme;
proxy_set_header X-Forwarded-Host \$http_host;
proxy_set_header Connection "";
proxy_pass http://localhost:9001/;
auth_basic "Protected";
auth_basic_user_file /etc/nginx/passwords;
}
proxy_set_header X-Forwarded-Proto \$origin_scheme;
proxy_set_header X-Forwarded-Host \$host;
client_max_body_size 100m; client_max_body_size 100m;
gzip on; gzip on;
@ -49,8 +71,6 @@ server {
root /appsmith-stacks/data/certificate/certbot; root /appsmith-stacks/data/certificate/certbot;
} }
proxy_set_header X-Forwarded-Proto \$origin_scheme;
proxy_set_header X-Forwarded-Host \$host;
location / { location / {
try_files \$uri /index.html =404; try_files \$uri /index.html =404;

View File

@ -1,23 +1,4 @@
FROM appsmith/appsmith-editor as frontend # Deploy using appsmith-ce image
FROM appsmith/appsmith-ce
FROM appsmith/appsmith-server
RUN mkdir -p /var/www/appsmith
COPY --from=appsmith/appsmith-editor /var/www/appsmith /var/www/appsmith
RUN apk add --update nginx && \
rm -rf /var/cache/apk/* && \
mkdir -p /tmp/nginx/client-body && \
apk --no-cache add gettext bash curl
COPY nginx.conf /etc/nginx/nginx.conf
COPY default.conf.template /etc/nginx/conf.d/default.conf.template
COPY bootstrap.sh /bootstrap.sh
COPY analytics.sh /analytics.sh
RUN chmod +x /analytics.sh
EXPOSE 80
ENTRYPOINT [ "/bin/sh -c" ]
CMD ["/bootstrap.sh"]
LABEL maintainer="tech@appsmith.com"

View File

@ -1,14 +0,0 @@
#!/bin/sh
APPSMITH_INSTALLATION_ID=$(curl -s 'https://api64.ipify.org')
curl -s --location --request POST 'https://hook.integromat.com/dkwb6i52am93pi30ojeboktvj32iw0fa' \
--header 'Content-Type: text/plain' \
--data-raw '{
"userId": "'"$APPSMITH_INSTALLATION_ID"'",
"event": "Installation Success",
"data": {
"platform": "heroku",
"os": "Alpine"
}
}'

View File

@ -1,57 +0,0 @@
#!/bin/bash
set -e
function get_maximum_heap(){
resource=$(ulimit -u)
echo "Resource : $resource"
if [[ "$resource" -le 256 ]]; then
maximum_heap=128
elif [[ "$resource" -le 512 ]]; then
maximum_heap=256
fi
}
function start_applcation(){
nginx
if [[ ! -z ${maximum_heap} ]]; then
backend_start_command="java -Xmx${maximum_heap}m -Dserver.port=8080 -Djava.security.egd='file:/dev/./urandom' -jar server.jar"
else
backend_start_command="java -Dserver.port=8080 -Djava.security.egd='file:/dev/./urandom' -jar server.jar"
fi
eval $backend_start_command
}
# Check for enviroment vairalbes
if [[ -z "${APPSMITH_MAIL_ENABLED}" ]]; then
unset APPSMITH_MAIL_ENABLED # If this field is empty is might cause application crash
fi
if [[ -z "${APPSMITH_OAUTH2_GITHUB_CLIENT_ID}" ]] || [[ -z "${APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET}" ]]; then
unset APPSMITH_OAUTH2_GITHUB_CLIENT_ID # If this field is empty is might cause application crash
unset APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET
fi
if [[ -z "${APPSMITH_OAUTH2_GOOGLE_CLIENT_ID}" ]] || [[ -z "${APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET}" ]]; then
unset APPSMITH_OAUTH2_GOOGLE_CLIENT_ID # If this field is empty is might cause application crash
unset APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET
fi
if [[ -z "${APPSMITH_GOOGLE_MAPS_API_KEY}" ]]; then
unset APPSMITH_GOOGLE_MAPS_API_KEY
fi
if [[ -z "${APPSMITH_RECAPTCHA_SITE_KEY}" ]] || [[ -z "${APPSMITH_RECAPTCHA_SECRET_KEY}" ]] || [[ -z "${APPSMITH_RECAPTCHA_ENABLED}" ]]; then
unset APPSMITH_RECAPTCHA_SITE_KEY # If this field is empty is might cause application crash
unset APPSMITH_RECAPTCHA_SECRET_KEY
unset APPSMITH_RECAPTCHA_ENABLED
fi
cat /etc/nginx/conf.d/default.conf.template | envsubst "$(printf '$%s,' $(env | grep -Eo '^APPSMITH_[A-Z0-9_]+'))" | sed -e 's|\${\(APPSMITH_[A-Z0-9_]*\)}||g' > /etc/nginx/conf.d/default.conf.template.1
envsubst "\$PORT" < /etc/nginx/conf.d/default.conf.template.1 > /etc/nginx/conf.d/default.conf
get_maximum_heap
start_applcation

View File

@ -1,55 +0,0 @@
server {
listen $PORT default_server;
client_max_body_size 100m;
gzip on;
root /var/www/appsmith;
index index.html index.htm;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header X-Forwarded-Host $host;
location / {
try_files $uri /index.html =404;
sub_filter __APPSMITH_SENTRY_DSN__ '${APPSMITH_SENTRY_DSN}';
sub_filter __APPSMITH_SMART_LOOK_ID__ '${APPSMITH_SMART_LOOK_ID}';
sub_filter __APPSMITH_OAUTH2_GOOGLE_CLIENT_ID__ '${APPSMITH_OAUTH2_GOOGLE_CLIENT_ID}';
sub_filter __APPSMITH_OAUTH2_GITHUB_CLIENT_ID__ '${APPSMITH_OAUTH2_GITHUB_CLIENT_ID}';
sub_filter __APPSMITH_MARKETPLACE_ENABLED__ '${APPSMITH_MARKETPLACE_ENABLED}';
sub_filter __APPSMITH_SEGMENT_KEY__ '${APPSMITH_SEGMENT_KEY}';
sub_filter __APPSMITH_ALGOLIA_API_ID__ '${APPSMITH_ALGOLIA_API_ID}';
sub_filter __APPSMITH_ALGOLIA_SEARCH_INDEX_NAME__ '${APPSMITH_ALGOLIA_SEARCH_INDEX_NAME}';
sub_filter __APPSMITH_ALGOLIA_API_KEY__ '${APPSMITH_ALGOLIA_API_KEY}';
sub_filter __APPSMITH_CLIENT_LOG_LEVEL__ '${APPSMITH_CLIENT_LOG_LEVEL}';
sub_filter __APPSMITH_GOOGLE_MAPS_API_KEY__ '${APPSMITH_GOOGLE_MAPS_API_KEY}';
sub_filter __APPSMITH_TNC_PP__ '${APPSMITH_TNC_PP}';
sub_filter __APPSMITH_VERSION_ID__ '${APPSMITH_VERSION_ID}';
sub_filter __APPSMITH_VERSION_RELEASE_DATE__ '${APPSMITH_VERSION_RELEASE_DATE}';
sub_filter __APPSMITH_INTERCOM_APP_ID__ '${APPSMITH_INTERCOM_APP_ID}';
sub_filter __APPSMITH_MAIL_ENABLED__ '${APPSMITH_MAIL_ENABLED}';
sub_filter __APPSMITH_DISABLE_TELEMETRY__ '${APPSMITH_DISABLE_TELEMETRY}';
sub_filter __APPSMITH_RECAPTCHA_SITE_KEY__ '${APPSMITH_RECAPTCHA_SITE_KEY}';
sub_filter __APPSMITH_RECAPTCHA_SECRET_KEY__ '${APPSMITH_RECAPTCHA_SECRET_KEY}';
sub_filter __APPSMITH_RECAPTCHA_ENABLED__ '${APPSMITH_RECAPTCHA_ENABLED}';
sub_filter __APPSMITH_DISABLE_INTERCOM__ '${APPSMITH_DISABLE_INTERCOM}';
sub_filter __APPSMITH_FORM_LOGIN_DISABLED__ '${APPSMITH_FORM_LOGIN_DISABLED}';
sub_filter __APPSMITH_SIGNUP_DISABLED__ '${APPSMITH_SIGNUP_DISABLED}';
}
location /api {
proxy_pass http://localhost:8080;
}
location /oauth2 {
proxy_pass http://localhost:8080;
}
location /login {
proxy_pass http://localhost:8080;
}
}

View File

@ -1,41 +0,0 @@
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '"$time_local" client=$remote_addr '
'method=$request_method request="$request" '
'request_length=$request_length '
'status=$status bytes_sent=$bytes_sent '
'body_bytes_sent=$body_bytes_sent '
'referer=$http_referer '
'http_x_forwarded_for=$http_x_forwarded_for '
'user_agent="$http_user_agent" '
'upstream_addr=$upstream_addr '
'upstream_status=$upstream_status '
'request_time=$request_time '
'upstream_response_time=$upstream_response_time '
'upstream_connect_time=$upstream_connect_time '
'upstream_header_time=$upstream_header_time';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}