Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 14 additions & 22 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,29 +1,21 @@
FROM php:7.4-apache as builder
FROM node:22.12-alpine AS builder

RUN apt-get update && apt-get install -y git ssl-cert \
&& git clone 'https://github.com/SimplyEdit/simplycode.git' /app/simplycode
RUN apk add --no-cache bash git \
&& mkdir /app \
&& git -C /app/ clone 'https://github.com/SimplyEdit/simplycode-electron.git' \
&& git -C /app/ clone 'https://github.com/SimplyEdit/simplyedit-backend.git' \
&& npm --prefix /app/simplycode-electron install

FROM php:7.4-apache

COPY --from=builder /app/simplycode/lib /var/www/lib
COPY --from=builder /app/simplycode/www/api/.htaccess /var/www/html/api/.htaccess
COPY --from=builder /app/simplycode/www/api/data/generated.html /var/www/html/simplycode/index.html
COPY --from=builder /app/simplycode/www/api/index.php /var/www/html/api/index.php
COPY --from=builder /app/simplycode/www/css /var/www/html/simplycode/css
COPY --from=builder /app/simplycode/www/js /var/www/html/simplycode/js
COPY --from=builder /app/simplycode/www/simply /var/www/html/simplycode/simply
COPY lib/ /var/www/lib/
COPY html/ /var/www/html/

COPY --from=builder /etc/ssl/certs/ssl-cert-snakeoil.pem /etc/ssl/certs/ssl-cert-snakeoil.pem
COPY --from=builder /etc/ssl/private/ssl-cert-snakeoil.key /etc/ssl/private/ssl-cert-snakeoil.key
COPY --from=builder /app/simplycode-electron/simplycode/ /var/www/html/simplycode/
COPY --from=builder /app/simplyedit-backend/www/ /var/www/www/

COPY 000-default.conf /etc/apache2/sites-available/000-default.conf
COPY entrypoint.sh /entrypoint.sh
COPY 403.php /var/www/html/403.php
RUN echo "ServerName simplycode" >> /etc/apache2/apache2.conf \
&& a2enmod --quiet rewrite ssl headers \
&& chmod +x /var/www/lib/entrypoint.sh

RUN a2enmod --quiet rewrite ssl headers \
&& chmod +x /entrypoint.sh \
&& ln -s /var/www/html/simplycode/js/ /var/www/html/js \
&& ln -s /var/www/www/api/data/generated.html /var/www/html/index.html \
&& mkdir /var/www/html/data && echo '{}' > /var/www/html/data/data.json

ENTRYPOINT ["/entrypoint.sh"]
ENTRYPOINT ["/var/www/lib/entrypoint.sh"]
231 changes: 231 additions & 0 deletions bin/run-simplycode-docker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
#!/usr/bin/env bash

set -o errexit # Exit script when a command exits with non-zero status.
set -o errtrace # Exit on error inside any functions or sub-shells.
set -o nounset # Exit script on use of an undefined variable.
set -o pipefail # Return exit status of the last command in the pipe that exited with a non-zero exit code

: "${DOCKER:=docker}"

# ==============================================================================
# Exit codes
# ------------------------------------------------------------------------------
: readonly -i "${EXIT_OK:=0}"
: readonly -i "${EXIT_NOT_ENOUGH_PARAMETERS:=65}"
: readonly -i "${EXIT_INVALID_PARAMETER:=66}"
: readonly -i "${EXIT_COULD_NOT_FIND_DIRECTORY:=75}"
: readonly -i "${EXIT_NOT_CORRECT_TYPE:=81}"

# ------------------------------------------------------------------------------
# Foreground colors
# ------------------------------------------------------------------------------
: readonly "${COLOR_BLUE:=$(tput setaf 4)}"
: readonly "${COLOR_GREEN:=$(tput setaf 2)}"
: readonly "${COLOR_RED:=$(tput setaf 1)}"
: readonly "${COLOR_WHITE:=$(tput setaf 7)}"
# ------------------------------------------------------------------------------
: readonly "${RESET_TEXT:=$(tput sgr0)}" # turn off all attributes
# ==============================================================================


# ==============================================================================
## Run the SimplyCode Docker container
# ------------------------------------------------------------------------------
## \nUsage: $0 [-dh][-i <docker-image>] <project-path>
##
## Where:
## <docker-image> is an alternative Docker image to use
## <project-path> is the path to the SimplyCode project to run
##
## Options:
## -d|--dry-run Show the command that would be run without executing it
## -h|--help Print this help dialogue and exit
## -i|--docker-image=<docker-image> Use the specified Docker image
##
## Any additional arguments will be passed to the `docker run` command.
##
## For example:
##
## $0 <project-path> /bin/bash
##
## The Docker executable can be overridden by setting the DOCKER environmental
## variable before calling this script:
##
## DOCKER=/usr/local/docker $0 <project-path>
##
## The SimplyCode Docker container will be run with the given project path mounted
## to the container's /var/www/www/api/data directory. If the project has an assets
## directory, this will be mounted to /var/www/html/assets.
# ==============================================================================
usage() {
local sScript sUsage

sScript="$(basename "$0")"
sUsage="$(grep '^##' < "$0" | cut -c4-)"

echo -e "${sUsage//\$0/${sScript}}"
}

error(){
message "ERROR" "${COLOR_RED}" "${@}" >&2
}

info(){
message "INFO" "${COLOR_BLUE}" "${@}"
}

message(){
local sType="${1?Three parameters required: <type> <color> <message>}"
local sColor="${2?Three parameters required: <type> <color> <message>}"
local sMessage="${3?Three parameters required: <type> <color> <message>}"

echo -e "${COLOR_WHITE}[${sColor}${sType}${COLOR_WHITE}]${RESET_TEXT} ${sMessage}"

# Each additional parameter will be treated as extra information to display with the error
if [[ "$#" -gt 3 ]]; then
shift 3
for sMessage in "$@"; do
echo -e " ${sMessage}"
done
fi
}

run_simplycode_docker() {
dryRun() {
local sResult

DOCKER='echo'
sResult=$(executeCommand "${@}")

iLines=$(echo "${sResult}" | sed -E 's/ --/\n--/g' | wc -l)
sResult="$(echo -n "${sResult}" | sed -E 's/ --/ \\\n --/g' | sed -n "1,${iLines}p")"

echo -en "docker "
echo -n "${sResult}" | head -n -1
echo -n "${sResult}" | tail -n 1 | cut -d ' ' -f 5-6 | sed -E 's/$/ \\/g' | sed 's/^/ /'
echo -n "${sResult}" | tail -n 1 | cut -d ' ' -f 7- | sed -E 's/ / \\\n/g' | sed 's/^/ /'
}

executeCommand() {
local sDockerImage sProjectPath

readonly sDockerImage="${1?Two parameters required: <docker-image> <project-path>}"
shift
readonly sProjectPath="${1?Two parameters required: <docker-image> <project-path>}"
shift

# ======================================================================
# Build the run command
# ----------------------------------------------------------------------
local -a aCommand=("${DOCKER}" 'run')

aCommand+=(
'--env' "USER_GID=$(id -g)"
'--env' "USER_ID=$(id -u)"
'--interactive'
'--network=default'
'--publish' '80:80'
'--publish' '443:443'
'--rm'
'--tty'
'--volume' "${sProjectPath}:/var/www/www/api/data"
)

if [[ -d "${sProjectPath}/assets" ]]; then
aCommand+=(
'--volume' "${sProjectPath}/assets:/var/www/html/assets"
)
fi

aCommand+=(
"${sDockerImage}"
"${@}"
)

# @TODO: Split command creation and execution into separate functions
# so dry-run can be simplified

"${aCommand[@]}"
}

local -a aParameters
local sArgument sDockerImage
local bDryRun=false

aParameters=()

sDockerImage='ghcr.io/simplyedit/simplycode-docker:main'

while (( "$#" )); do
sArgument="${1}"
shift
case "${sArgument}" in
-d | --dry-run)
bDryRun=true
;;

-\? | -h | --help)
usage
exit "${EXIT_OK}"
;;

-i | --docker-image | --docker-image=?*)
# If the parameter contains a `=` the path is part of the param, so we need to split it to get the value
if grep '=' <(echo "${sArgument}");then
sDockerImage="${sArgument#*=}"
else
# Else, the next param is the value, unless no param is provided
if [[ -n "${1:-}" && ! "${1}" =~ ^- ]]; then
sDockerImage="${1}"
shift
else
error "No value provided for ${sDockerImage}" "Call with --help for more information."
exit "${EXIT_NOT_ENOUGH_PARAMETERS}"
fi
fi
;;

--*|-*)
error "Invalid option '${sArgument}'" "Call with --help for more information."
exit "${EXIT_INVALID_PARAMETER}"
;;

*)
aParameters+=("${sArgument}")
;;
esac
done

if [[ "${#aParameters[@]}" -lt 1 ]]; then
error "One parameter required: <project-path>" "Call with --help for more information."
exit "${EXIT_NOT_ENOUGH_PARAMETERS}"
fi

local sProjectPath="${aParameters[0]}"
sProjectPath="$(realpath "${sProjectPath}")"
aParameters=( "${aParameters[@]:1}" )

if [[ ! -e "${sProjectPath}" ]];then
error "Could not find directory: ${sProjectPath}"
exit "${EXIT_COULD_NOT_FIND_DIRECTORY}"
elif [[ ! -d "${sProjectPath}" ]];then
error "Provided path is not a directory: ${sProjectPath}"
exit "${EXIT_NOT_CORRECT_TYPE}"
fi

if [[ "${bDryRun}" == true ]]; then
info "Dry run enabled. The following command would be run:\n"
dryRun "${sDockerImage}" "${sProjectPath}" "${aParameters[@]}"
echo ""
else
executeCommand "${sDockerImage}" "${sProjectPath}" "${aParameters[@]}"
fi
}

if [[ ${BASH_SOURCE[0]} != "$0" ]]; then
export -f run_simplycode_docker
else
run_simplycode_docker "${@}"
fi

#EOF
39 changes: 39 additions & 0 deletions html/.htaccess
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<Files settings.json>
<Limit GET>
Order Allow,Deny
Deny from all
</Limit>
</Files>
<Files data.json>
Header set Cache-Control "max-age=0, public, must-revalidate"
</Files>
RewriteEngine on
#<Limit POST PUT DELETE>
# RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
#
# RewriteCond %{REQUEST_METHOD} PUT
# RewriteRule ^(.*)$ simply-edit/store.php [L]
#
# RewriteCond %{REQUEST_METHOD} DELETE
# RewriteRule ^(.*)$ simply-edit/store.php [L]
#
# RewriteCond %{QUERY_STRING} _method=(PUT|DELETE)
# RewriteRule ^(.*)$ simply-edit/store.php [L]
#</Limit>
<Limit GET POST>
RewriteRule ^logout$ simply-edit/logout.php [L]
#RewriteRule ^login$ simply-edit/login.php [L]
</Limit>
<Limit GET>
RewriteCond %{HTTP_USER_AGENT} Lynx|w3m|googlebot|baiduspider|facebookexternalhit|twitterbot|rogerbot|linkedinbot|embedly|quora\ link\ preview|showyoubot|outbrain|pinterest|slackbot|vkShare|Validator [NC,OR]
RewriteCond %{QUERY_STRING} _escaped_fragment_

# Only proxy the request to Prerender if it's a request for HTML
RewriteRule ^(?!.*?(\.js|\.css|\.xml|\.less|\.png|\.jpg|\.jpeg|\.gif|\.pdf|\.doc|\.txt|\.ico|\.rss|\.zip|\.mp3|\.rar|\.exe|\.wmv|\.doc|\.avi|\.ppt|\.mpg|\.mpeg|\.tif|\.wav|\.mov|\.psd|\.ai|\.xls|\.mp4|\.m4a|\.swf|\.dat|\.dmg|\.iso|\.flv|\.m4v|\.torrent|\.ttf|\.woff))(.*) simply-edit/prerender.php [L]
</Limit>

Options +Indexes

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* simply-edit/router.php [L]
9 changes: 9 additions & 0 deletions html/api/.htaccess
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
RewriteEngine on
<Limit POST PUT DELETE>
RewriteCond %{QUERY_STRING} _method=(GET|PUT|DELETE)
RewriteRule ^(.*)$ index.php [L]
</Limit>

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L]
Loading
Loading