Skip to content

Commit

Permalink
- Changed everything to use project_root instead of /app, in order to…
Browse files Browse the repository at this point in the history
… disambiguate this from the project_root/app directory

- Added sync excludes for common unneeded directories that may exist in dev workdirs
- Changed docker-sync to sync the full project directory
- Changed Dockerfile.rails to bundle in into a separate directory. This is to preserve any changes bundler will make to the Gemfile.lock, so that we can copy it back to the host once sync is started. I'm running an additional command at the end of the Dockerfile to copy of the lock file back to project_root in the case when someone is not using docker-sync
- The healthy dependency condition is no longer available in v3 of docker compose. Copied the wait-for-it script referenced in peter-evans/docker-compose-healthcheck#3 and added a rails entry script that will handle all the things associated with first starting the rails app, including waiting for mysql to start.
  • Loading branch information
Justin Gondron committed Jul 26, 2018
1 parent eb48ed1 commit 05d31a6
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 9 deletions.
6 changes: 4 additions & 2 deletions docker-compose.yml
Expand Up @@ -23,11 +23,13 @@ services:
build:
context: .
dockerfile: docker/Dockerfile.rails
command: bundle exec thin start -p 3000 --ssl --ssl-key-file dev_server_keys/server.key --ssl-cert-file dev_server_keys/server.crt
command: bash docker/rails_entry.sh
environment:
BUNDLE_PATH: "/bundle"
ports:
- "3000:3000"
volumes:
- rails-app-sync:/app/app:nocopy
- rails-app-sync:/project_root:nocopy
depends_on:
- mysql
- jetty
Expand Down
5 changes: 2 additions & 3 deletions docker-sync.yml
Expand Up @@ -4,6 +4,5 @@ options:
verbose: true
syncs:
rails-app-sync: # tip: add -sync and you keep consistent names as a convention
src: './app'
# sync_strategy: 'native_osx' # not needed, this is the default now
sync_excludes: ['ignored_folder', '.ignored_dot_folder']
src: '.'
sync_excludes: ['.git', 'tmp', 'jetty', 'vendor/bundle']
16 changes: 12 additions & 4 deletions docker/Dockerfile.rails
@@ -1,9 +1,17 @@
FROM ruby:2.1.10

RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /app

WORKDIR /app
COPY . /app
# Put the installed gems outside of project_root so that the sync volume won't interfere
RUN mkdir /bundle
COPY Gemfile /bundle
COPY Gemfile.lock /bundle
WORKDIR /bundle
RUN bundle install --without headless --path /bundle

RUN bundle install --without headless
RUN mkdir /project_root
WORKDIR /project_root
COPY . /project_root

# Gemfile.lock may have changed after bundling, copy it back into the project_root
RUN cp /bundle/Gemfile.lock /project_root/
7 changes: 7 additions & 0 deletions docker/rails_entry.sh
@@ -0,0 +1,7 @@
# All the things that will execute when starting the rails service
# Copy the generated lock file back into the project root. This is to sync this change back to the
# application after the container has mounted the sync volume
cp /bundle/Gemfile.lock ./
bash docker/wait-for-it.sh mysql:3306
bundle exec rake db:schema:load
bundle exec thin start -p 3000 --ssl --ssl-key-file dev_server_keys/server.key --ssl-cert-file dev_server_keys/server.crt
177 changes: 177 additions & 0 deletions docker/wait-for-it.sh
@@ -0,0 +1,177 @@
#!/usr/bin/env bash
# Use this script to test if a given TCP host/port are available

cmdname=$(basename $0)

echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi }

usage()
{
cat << USAGE >&2
Usage:
$cmdname host:port [-s] [-t timeout] [-- command args]
-h HOST | --host=HOST Host or IP under test
-p PORT | --port=PORT TCP port under test
Alternatively, you specify the host and port as host:port
-s | --strict Only execute subcommand if the test succeeds
-q | --quiet Don't output any status messages
-t TIMEOUT | --timeout=TIMEOUT
Timeout in seconds, zero for no timeout
-- COMMAND ARGS Execute command with args after the test finishes
USAGE
exit 1
}

wait_for()
{
if [[ $TIMEOUT -gt 0 ]]; then
echoerr "$cmdname: waiting $TIMEOUT seconds for $HOST:$PORT"
else
echoerr "$cmdname: waiting for $HOST:$PORT without a timeout"
fi
start_ts=$(date +%s)
while :
do
if [[ $ISBUSY -eq 1 ]]; then
nc -z $HOST $PORT
result=$?
else
(echo > /dev/tcp/$HOST/$PORT) >/dev/null 2>&1
result=$?
fi
if [[ $result -eq 0 ]]; then
end_ts=$(date +%s)
echoerr "$cmdname: $HOST:$PORT is available after $((end_ts - start_ts)) seconds"
break
fi
sleep 1
done
return $result
}

wait_for_wrapper()
{
# In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
if [[ $QUIET -eq 1 ]]; then
timeout $BUSYTIMEFLAG $TIMEOUT $0 --quiet --child --host=$HOST --port=$PORT --timeout=$TIMEOUT &
else
timeout $BUSYTIMEFLAG $TIMEOUT $0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT &
fi
PID=$!
trap "kill -INT -$PID" INT
wait $PID
RESULT=$?
if [[ $RESULT -ne 0 ]]; then
echoerr "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $HOST:$PORT"
fi
return $RESULT
}

# process arguments
while [[ $# -gt 0 ]]
do
case "$1" in
*:* )
hostport=(${1//:/ })
HOST=${hostport[0]}
PORT=${hostport[1]}
shift 1
;;
--child)
CHILD=1
shift 1
;;
-q | --quiet)
QUIET=1
shift 1
;;
-s | --strict)
STRICT=1
shift 1
;;
-h)
HOST="$2"
if [[ $HOST == "" ]]; then break; fi
shift 2
;;
--host=*)
HOST="${1#*=}"
shift 1
;;
-p)
PORT="$2"
if [[ $PORT == "" ]]; then break; fi
shift 2
;;
--port=*)
PORT="${1#*=}"
shift 1
;;
-t)
TIMEOUT="$2"
if [[ $TIMEOUT == "" ]]; then break; fi
shift 2
;;
--timeout=*)
TIMEOUT="${1#*=}"
shift 1
;;
--)
shift
CLI=("$@")
break
;;
--help)
usage
;;
*)
echoerr "Unknown argument: $1"
usage
;;
esac
done

if [[ "$HOST" == "" || "$PORT" == "" ]]; then
echoerr "Error: you need to provide a host and port to test."
usage
fi

TIMEOUT=${TIMEOUT:-15}
STRICT=${STRICT:-0}
CHILD=${CHILD:-0}
QUIET=${QUIET:-0}

# check to see if timeout is from busybox?
# check to see if timeout is from busybox?
TIMEOUT_PATH=$(realpath $(which timeout))
if [[ $TIMEOUT_PATH =~ "busybox" ]]; then
ISBUSY=1
BUSYTIMEFLAG="-t"
else
ISBUSY=0
BUSYTIMEFLAG=""
fi

if [[ $CHILD -gt 0 ]]; then
wait_for
RESULT=$?
exit $RESULT
else
if [[ $TIMEOUT -gt 0 ]]; then
wait_for_wrapper
RESULT=$?
else
wait_for
RESULT=$?
fi
fi

if [[ $CLI != "" ]]; then
if [[ $RESULT -ne 0 && $STRICT -eq 1 ]]; then
echoerr "$cmdname: strict mode, refusing to execute subprocess"
exit $RESULT
fi
exec "${CLI[@]}"
else
exit $RESULT
fi

0 comments on commit 05d31a6

Please sign in to comment.