Unverified Commit dae1717d authored by CSammy's avatar CSammy Committed by Dennis Schubert

Add docker setup for development

closes #7870
parent 0133a9f3
......@@ -2,6 +2,8 @@
## Refactor
* Make setting up a development environment 9001% easier by adding a Docker-based setup [#7870](https://github.com/diaspora/diaspora/pull/7870)
## Bug fixes
## Features
......
FROM ruby:2.4.4-slim-stretch
RUN DEBIAN_FRONTEND=noninteractive \
apt-get update && \
apt-get install -y -qq \
build-essential \
cmake \
curl \
ghostscript \
git \
imagemagick \
libcurl4-openssl-dev \
libidn11-dev \
libmagickwand-dev \
libmariadbclient-dev \
libpq-dev \
libssl-dev \
libxml2-dev \
libxslt-dev \
nodejs \
gosu \
&& \
rm -rf /var/lib/apt/lists/*
ARG DIA_UID
ARG DIA_GID
ENV HOME="/home/diaspora" \
GEM_HOME="/diaspora/vendor/bundle"
RUN addgroup --gid $DIA_GID diaspora && \
adduser \
--no-create-home \
--disabled-password \
--gecos "" \
--uid $DIA_UID \
--gid $DIA_GID \
diaspora \
&& \
mkdir $HOME /diaspora && \
chown -R diaspora:diaspora $HOME /diaspora
RUN curl -L \
https://cifiles.diasporafoundation.org/phantomjs-2.1.1-linux-x86_64.tar.bz2 \
| tar -xj -C /usr/local/bin \
--transform='s#.*/##' \
phantomjs-2.1.1-linux-x86_64/bin/phantomjs
ENV BUNDLE_PATH="$GEM_HOME" \
BUNDLE_BIN="$GEM_HOME/bin" \
BUNDLE_APP_CONFIG="/diaspora/.bundle"
ENV PATH $BUNDLE_BIN:$PATH
COPY docker-entrypoint.sh /entrypoint.sh
COPY docker-exec-entrypoint.sh /exec-entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["./script/server"]
version: "3.4"
volumes:
postgresql_data:
mysql_data:
dia_data_tmp:
dia_data_bundle:
services:
diaspora:
build:
context: .
dockerfile: Dockerfile
args:
DIA_UID: "${DIASPORA_ROOT_UID}"
DIA_GID: "${DIASPORA_ROOT_GID}"
image: diaspora:dev-latest
volumes:
- "${DIASPORA_ROOT}:/diaspora:rw"
- dia_data_tmp:/diaspora/tmp
- dia_data_bundle:/diaspora/vendor/bundle
ports:
- 8080:3000
depends_on:
- "${DIASPORA_DOCKER_DB}"
postgresql:
image: postgres:10.3
ports:
- 55432:5432
volumes:
- postgresql_data:/var/lib/postgresql
mysql:
image: mariadb:10.2
ports:
- 53306:3306
volumes:
- mysql_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: mysql
#!/bin/bash
# ----- Ensure correct ownership of /diaspora -----
dia_home=/home/diaspora
HOST_UID=$(stat -c %u /diaspora)
HOST_GID=$(stat -c %g /diaspora)
if ! getent group $HOST_GID >/dev/null; then
groupmod --gid $HOST_GID diaspora
fi
if ! getent passwd $HOST_UID >/dev/null; then
usermod --uid $HOST_UID --gid $HOST_GID diaspora
fi
chown -R $HOST_UID:$HOST_GID /home/diaspora
mkdir -p /diaspora/tmp/pids
chown $HOST_UID:$HOST_GID /diaspora/tmp /diaspora/tmp/pids /diaspora/vendor/bundle
# ----- Wait for DB ----
if [ -z $DIA_NODB ] || [ ! $DIA_NODB -eq 1 ]; then
if grep -qFx " <<: *postgresql" /diaspora/config/database.yml; then
host=postgresql
port=5432
else
host=mysql
port=3306
fi
c=0
trap '{ exit 1; }' INT
while ! (< /dev/tcp/${host}/${port}) 2>/dev/null; do
printf "\rWaiting for $host:$port to become ready ... ${c}s"
sleep 1
((c++))
done
trap - INT
if [ ! -z $c ]; then
printf "\rWaiting for $host:$port to become ready ... done (${c}s)\n"
fi
fi
cd /diaspora
gosu $HOST_UID:$HOST_GID "$@"
#!/bin/bash
HOST_UID=$(stat -c %u /diaspora)
HOST_GID=$(stat -c %g /diaspora)
cd /diaspora
gosu $HOST_UID:$HOST_GID "$@"
#!/bin/bash
# ----- Usage information -----
print_usage() {
# Print help for the first argument
case "$1" in
# management
setup)
echo; echo "Set up the environment for diaspora*"
echo; echo "This command is an alias for the execution of the commands"
echo "build, config, bundle, migrate and setup-tests, in that order."
print_usage_header "setup [options]" \
" --force Rebuild image without using Docker's cache;" \
" overwrite existing configuration" \
" --mysql Use MySQL as database (PostgreSQL is default)"
;;
start)
echo; echo "Start diaspora* (includes database)"
print_usage_header "start [options]" \
"-d Run in background"
;;
stop)
echo; echo "Stop diaspora* (includes database)"
print_usage_header "stop"
;;
restart)
echo; echo "Restart diaspora* using bin/eye (fast restart)"
print_usage_header "restart [options]" \
" --full Restart entire container"
;;
logs)
echo; echo "Follow log output of the running diaspora* instance"
print_usage_header "logs [options]" \
"-a, --all Follow all containers, including databases"
;;
status)
echo; echo "Show currently running diaspora* Docker container(s) and related image(s)"
print_usage_header "status"
;;
clean)
echo; echo "Delete diaspora* Docker containers and volumes (includes database)"
print_usage_header "clean [options]" \
" --config Delete configuration files as well"
;;
# test & development
cucumber)
echo; echo "Run cucumber tests"
echo; echo "The specified cucumber tests will be executed. If none are given, all"
echo "tests are executed."
print_usage_header "cucumber [TEST...]"
;;
jasmine)
echo; echo "Run all jasmine tests"
print_usage_header "jasmine"
;;
rspec)
echo; echo "Run rspec tests"
echo; echo "The specified rspec tests will be executed. If none are given, all"
echo "tests will be executed."
print_usage_header "rspec"
;;
pronto)
echo; echo "Run pronto checks"
print_usage_header "pronto"
;;
migrate)
echo; echo "Execute pending migrations (incl. database setup)"
print_usage_header "migrate [options]" \
"-d Run in background"
;;
# misc
build)
echo; echo "(Re-)Build Docker image diaspora:dev-latest"
print_usage_header "build [options]" \
" --no-cache Rebuild image without using Docker's cache"
;;
bundle)
echo; echo "Install gems using bundle into $DIASPORA_ROOT"
print_usage_header "bundle [options]" \
"-d Run in background"
;;
config)
echo; echo "Create basic configuration files for usage with PostgreSQL (default)"
print_usage_header "config [options]" \
" --mysql Use MySQL as database (PostgreSQL is default)" \
" --overwrite Overwrite existing configuration"
;;
exec)
echo; echo "Execute a command in a diaspora* Docker container"
echo; echo "If there is no running diaspora* Docker container, a new one is created"
echo "and started."
print_usage_header "exec [options] COMMAND [ARGS...]" \
"-d Run in background"
;;
help)
echo; echo "Show help on a command"
print_usage_header "help COMMAND"
;;
setup-tests)
echo; echo "Prepare cached files and database contents for tests"
print_usage_header "setup-tests"
;;
*)
print_usage_full
;;
esac
}
print_usage_header() {
# Print formatted usage information for COMMAND
# Usage: print_usage_header COMMAND [FLAG_DESCRIPTION...]
echo; echo "Usage: $1"
shift
if [ $# -gt 0 ]; then
echo; echo "Options:"
while [ $# -gt 0 ]; do
echo " $1"
shift
done
fi
}
print_usage_full() {
# Print overview of available commands
# $SCRIPT_NAME [help|-h|--help] leads here
echo; echo "Setup and run a diaspora instance for development in no time."
print_usage_header "$SCRIPT_NAME COMMAND"
echo
echo "Management Commands:"
echo " setup Prepare diaspora* to run for development"
echo " start Start diaspora*"
echo " stop Stop diaspora*"
echo " restart Restart of diaspora*"
echo " logs Follow log output of diaspora*"
echo " status Show current instance status of diaspora*"
echo " clean Reset diaspora* instance"
echo
echo "Test and Development Commands:"
echo " cucumber Run cucumber tests"
echo " jasmine Run jasmine tests"
echo " rspec Run rspec tests"
echo " pronto Run pronto checks"
echo " migrate Execute pending migrations"
echo
echo "Misc. Commands:"
echo " build Build basic diaspora* environment"
echo " bundle (Re-)Install gems for diaspora*"
echo " config Configure diaspora*"
echo " exec Execute a command in the run environment (advanced)"
echo " help Show help for commands"
echo " setup-tests Prepare diaspora* test environment"
echo
echo "Run '$SCRIPT_NAME help COMMAND' for more information on a command."
}
# ----- Helper functions -----
dia_fetch_upstream() {
# Add and fetch upstream develop branch
if ! git remote show | grep -q '^upstream$'; then
git remote add upstream https://github.com/diaspora/diaspora.git
fi
git fetch upstream develop
}
dia_is_configured() {
# Check if config files exist
[ -f "$DIASPORA_CONFIG_DB" ] && [ -f "$DIASPORA_CONFIG_DIA" ]
}
exit_if_unconfigured() {
# Exit if config does not seem complete
if ! dia_is_configured; then
echo "Fatal: Config files missing. Run the 'setup' or 'config' command to configure."
exit 1
fi
}
dia_is_running() {
# Check if diaspora container is running
docker-compose ps --services --filter status=running | grep -qx 'diaspora'
}
dia_is_db_running() {
# Check if db container is running
docker-compose ps --services --filter status=running | grep -qx $DIASPORA_DOCKER_DB
}
dia_get_db() {
# Get currently configured or assumed db type
grep -q '^ <<: \*mysql' "$DIASPORA_CONFIG_DB" 2>/dev/null && echo mysql || echo postgresql
}
# ----- Command functions -----
dia_build() {
if [ $# -gt 0 ] && [ "$1" == "--no-cache" ]; then nocache="--no-cache"; fi
# Build the diaspora Docker container (diaspora:dev-latest)
docker-compose build $nocache diaspora
}
dia_bundle() {
# Run bundle in order to install all gems into $DIASPORA_ROOT
# Do not start database, not required and sometimes not yet configured
echo "Installing gems via bundler ..."
docker-compose run \
--rm \
--no-deps $1 \
-e DIA_NODB=1 \
diaspora \
/bin/sh -c "gem install bundler && script/configure_bundler && bin/bundle install --full-index"
}
dia_clean() {
# Delete all containers and volumes
for i in "$@"; do
case "$i" in
--config)
dia_config_delete=1
;;
esac
done
docker-compose down -v
if [ ! -z $dia_config_delete ]; then
rm "$DIASPORA_CONFIG_DIA" "$DIASPORA_CONFIG_DB"
fi
}
dia_config() {
# Create rudimentary configuration files if they don't exist
echo "Configuring diaspora ..."
for i in "$@"; do
case "$i" in
--mysql)
dia_config_mysql=1
;;
--overwrite)
dia_config_delete=1
;;
esac
done
[ ! -f "$DIASPORA_ROOT"/public/source.tar.gz ] && touch "$DIASPORA_ROOT"/public/source.tar.gz
# Delete existing files if requested
if [ ! -z $dia_config_delete ]; then
rm "$DIASPORA_CONFIG_DIA" "$DIASPORA_CONFIG_DB"
fi
# Create new diaspora.yml if none exists
if [ ! -f "$DIASPORA_CONFIG_DIA" ]; then
cp "$DIASPORA_CONFIG_DIA".example "$DIASPORA_CONFIG_DIA"
fi
# Select database type
if [ -z $dia_config_mysql ]; then
export DIASPORA_DOCKER_DB=postgresql
else
export DIASPORA_DOCKER_DB=mysql
fi
# Create new database.yml if none exists
if [ ! -f "$DIASPORA_CONFIG_DB" ]; then
sed -E '
/^postgresql/,/^[[:alpha:]]/ {
s/host:.*/host: postgresql/
s/password.*/password: postgres/
}
/^mysql/,/^[[:alpha:]]/ {
s/host:.*/host: mysql/
s/password:.*/password: mysql/
}
/^common/,/^[[:alpha:]]/ {
s/^(\s+<<:).*/\1 *'$DIASPORA_DOCKER_DB'/
}' "$DIASPORA_CONFIG_DB".example > "$DIASPORA_CONFIG_DB"
fi
# Update exisiting database.yml to reflect correct database type
if [ "$(dia_get_db)" != "$DIASPORA_DOCKER_DB" ]; then
sed -E -i'' '
/^common/,/^[[:alpha:]]/ {
s/^(\s+<<:).*/\1 *'$DIASPORA_DOCKER_DB'/
}' "$DIASPORA_CONFIG_DB"
fi
}
dia_cucumber() {
# Run cucumber tests
if [ "$1" == "-d" ]; then detach="-d"; shift; fi
docker-compose run \
--rm $detach \
diaspora \
bin/cucumber "$@"
}
dia_exec() {
# Run a custom command inside a running diaspora container. Start a new one if necessary.
exit_if_unconfigured
if [ "$1" == "-d" ]; then detach="-d"; shift; fi
if dia_is_running; then
# Use a running container
docker-compose exec $detach diaspora /exec-entrypoint.sh "$@"
else
if ! dia_is_db_running; then not_running=1; fi
# Start a new container
echo "No running instance found, starting new one for command execution ..."
docker-compose run --rm $detach --service-ports diaspora "$@"
if [ ! -z $not_running ]; then
docker-compose stop $DIASPORA_DOCKER_DB
fi
fi
}
dia_jasmine() {
# Run jasmine tests
docker-compose run \
--rm $1 \
-e RAILS_ENV=test \
diaspora \
bin/rake jasmine:ci
}
dia_logs() {
# Show logs of running diaspora* instance
dia_follow=diaspora
for i in "$@"; do
case "$i" in
-a|--all)
dia_follow=""
;;
esac
done
docker-compose logs -f --tail=100 $dia_follow
}
dia_migrate() {
# Run migrations if configured
echo "Creating and/or migrating database ..."
exit_if_unconfigured
docker-compose run \
--rm $1 \
diaspora \
bin/rake db:create db:migrate
}
dia_pronto() {
# Run pronto checks
exit_if_unconfigured
cd "$DIASPORA_ROOT"
if git diff-index --quiet HEAD --; then
dia_fetch_upstream
fi
cd - >/dev/null
docker-compose run \
--rm \
--no-deps \
diaspora \
bin/pronto run --unstaged -c upstream/develop
}
dia_restart() {
# Restart diaspora inside container if already running; start new container otherwise
for i in "$@"; do
case "$i" in
--full)
dia_restart_full=1
;;
esac
done
if dia_is_running; then
if [ -z $dia_restart_full ]; then
docker-compose exec \
diaspora \
bin/eye restart diaspora
else
docker-compose restart
fi
else
dia_start
fi
}
dia_rspec() {
# Run rspec tests
exit_if_unconfigured
assets=""
# Assumption: If (and only if) the tested file is not available, assets need be regenerated
[ -f "$DIASPORA_ROOT"/public/404.html ] && assets="assets:generate_error_pages"
# Prepare database (and assets if necessary)
docker-compose run \
--rm \
-e RAILS_ENV=test \
diaspora \
bin/rake db:create db:migrate $assets
# Run tests
docker-compose run \
--rm \
diaspora \
bin/rspec "$@"
}
dia_setup() {
for i in "$@"; do
case "$i" in
--force)
build="$build --no-cache"
config="$config --overwrite"
;;
--mysql)
config="$config --mysql"
;;
esac
done
# Prepare the entire environment for development
(
set -e
dia_build $build
dia_config $config
dia_bundle $bundle
dia_migrate $migrate
dia_setup_tests $setup_tests
)
# stop db afterwards as it is not needed while dia is not running
docker-compose stop $DIASPORA_DOCKER_DB
}
dia_setup_tests() {
# Prepare all possible tests
# stop db if it was not running before
echo "Setting up environment for tests ..."
if ! dia_is_db_running; then stopdb="docker-compose stop $DIASPORA_DOCKER_DB"; fi
docker-compose run \
--rm \
-e RAILS_ENV=test \
diaspora \
bin/rake db:create db:migrate tests:generate_fixtures assets:generate_error_pages
$stopdb
}
dia_start() {
# Start all containers if config appears to exist
exit_if_unconfigured
if [ $# -eq 0 ]; then
options=--abort-on-container-exit
else
options=$1
fi
docker-compose up $options diaspora
}
dia_status() {
# Print running containers and current images
docker-compose ps
echo
docker-compose images
}
dia_stop() {
# Stop all containers
docker-compose stop
}
# ----- Variables -----
# Symlinks are treated as files
export SCRIPT_NAME=$(basename "${BASH_SOURCE[0]}")
export SCRIPT_ROOT=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)
# Assumption: The script is in the "script" subfolder of the diaspora root folder
export DIASPORA_ROOT=$(dirname "$SCRIPT_ROOT")
export DIASPORA_ROOT_UID=1001
export DIASPORA_ROOT_GID=1001
export DIASPORA_CONFIG_DIA=$DIASPORA_ROOT/config/diaspora.yml
export DIASPORA_CONFIG_DB=$DIASPORA_ROOT/config/database.yml
export DIASPORA_DOCKER_DB=$(dia_get_db)
export COMPOSE_FILE=$DIASPORA_ROOT/docker/develop/docker-compose.yml
export COMPOSE_PROJECT_NAME=diasporadev
# ----- Arg parsing -----
if [ $# -lt 1 ]; then
print_usage
exit 1
fi
dia_command=$1
shift
case "$dia_command" in
--help|-h)
print_usage_full
exit 0
;;
help)
if [ $# -lt 1 ]; then
print_usage_full
else
print_usage "$1"
fi
exit 0
;;
build)
dia_build "$@"
;;
bundle)
dia_bundle "$1"
;;
clean)
dia_clean "$@"
;;
config)
dia_config "$@"
;;
cucumber)
dia_cucumber "$@"
;;
exec)
dia_exec "$@"
;;
jasmine)
dia_jasmine
;;
logs)
dia_logs "$@"
;;
migrate)
dia_migrate "$@"
;;
pronto)
dia_pronto
;;
restart)
dia_restart "$@"
;;
rspec)
dia_rspec "$@"
;;
setup)
dia_setup "$@"
;;