diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..3176739f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +build +node_modules +test diff --git a/Dockerfile b/Dockerfile index 8199c809..c4cc2064 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,16 +1,12 @@ FROM node:12-alpine AS BUILD_IMAGE -# Create man folders which are required by postgres -RUN seq 1 8 | xargs -I{} mkdir -p /usr/share/man/man{} - # Install dependencies -RUN apk update \ - && apk add git python make g++ postgresql-client \ - && rm -rf /var/cache/apk/* +RUN apk update +RUN apk add --no-cache git python make g++ # Use changes to package.json to force Docker not to use the cache when we # change our application's NodeJS dependencies: -COPY package.json /tmp/package.json +COPY package*.json /tmp/ RUN cd /tmp && npm install RUN mkdir -p /usr/src/app && cp -a /tmp/node_modules /usr/src/app @@ -30,14 +26,11 @@ FROM node:12-alpine WORKDIR /usr/src/app # Copy from build image -COPY --from=BUILD_IMAGE /usr/src/app/build ./build -COPY --from=BUILD_IMAGE /usr/src/app/node_modules ./node_modules +COPY --from=BUILD_IMAGE /usr/src/app ./ # Copy runtime scripts into root -COPY --from=BUILD_IMAGE /usr/src/app/scripts/run.sh . -COPY --from=BUILD_IMAGE /usr/src/app/scripts/run-worker.sh . -COPY --from=BUILD_IMAGE /usr/src/app/scripts/wait-for-db.sh . +COPY --from=BUILD_IMAGE /usr/src/app/scripts/*.sh ./ EXPOSE 3000 -ENTRYPOINT ["./wait-for-db.sh"] +ENTRYPOINT ["./entrypoint.sh"] diff --git a/package.json b/package.json index 12d3374c..65d0ccb3 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,6 @@ "@babel/eslint-parser": "^7.13.10", "babel-plugin-add-module-exports": "^1.0.4", "concurrently": "^6.0.0", - "cross-env": "^7.0.3", "eslint": "^7.21.0", "eslint-config-prettier": "^8.1.0", "eslint-plugin-prettier": "^3.3.1", @@ -49,7 +48,6 @@ "nodemon": "^2.0.7", "prettier": "^2.2.1", "rimraf": "^3.0.2", - "sequelize-cli": "^6.2.0", "supertest": "^6.1.3", "truffle": "^5.2.3" }, @@ -63,6 +61,7 @@ "celebrate": "^13.0.4", "compression": "^1.7.4", "cors": "^2.8.5", + "cross-env": "^7.0.3", "dotenv": "^8.2.0", "express": "^4.17.1", "fast-json-stringify": "^2.5.1", @@ -75,6 +74,7 @@ "multer": "^1.4.2", "pg": "^8.5.1", "sequelize": "^6.5.0", + "sequelize-cli": "^6.2.0", "sharp": "^0.27.2", "web3": "^1.3.4", "winston": "^3.3.3" diff --git a/scripts/entrypoint.sh b/scripts/entrypoint.sh new file mode 100755 index 00000000..44e5dcd6 --- /dev/null +++ b/scripts/entrypoint.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +set -e + +CMD="$@" + +# Set default values +POSTGRES_PORT=${POSTGRES_PORT:-5432} +NODE_ENV=${NODE_ENV:-"production"} + +# Helper method to extract host and port from url +parse_url() { + # Extract the protocol + proto="$(echo $1 | grep :// | sed -e's,^\(.*://\).*,\1,g')" + # Remove the protocol + url=$(echo $1 | sed -e s,$proto,,g) + # Extract the host and port + hostport=$(echo $url | cut -d/ -f1) + # Extract host without port + host="$(echo $hostport | sed -e 's,:.*,,g')" + # Try to extract the port + port="$(echo $hostport | sed -e 's,^.*:,:,g' -e 's,.*:\([0-9]*\).*,\1,g' -e 's,[^0-9],,g')" + # Set port default when not given + if [ -z "$port" ] + then + [ "$proto" = "https://" ] && port=443 || port=80 + fi + echo "$host:$port" +} + +# Wait until graph node is ready +./wait-for-it.sh "$(parse_url $GRAPH_NODE_ENDPOINT)" -t 60 + +# Wait until database is ready +./wait-for-it.sh "$POSTGRES_HOST:$POSTGRES_PORT" -t 60 + +# Set DATABASE_URL env variable in correct format for application +export DATABASE_URL=postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/$POSTGRES_DATABASE_API + +# Run migrations +npm run db:migrate +npm run db:seed + +# Finally execute start command +exec $CMD diff --git a/scripts/wait-for-db.sh b/scripts/wait-for-db.sh deleted file mode 100755 index 9b22720b..00000000 --- a/scripts/wait-for-db.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh - -set -e - -CMD="$@" - -# Set default values -POSTGRES_PORT=${POSTGRES_PORT:-5432} -NODE_ENV=${NODE_ENV:-"production"} - -# Wait until database is ready -while ! PGPASSWORD=$POSTGRES_PASSWORD pg_isready -h $POSTGRES_HOST -p $POSTGRES_PORT -U "$POSTGRES_USER" -d "$POSTGRES_DATABASE_API" > /dev/null 2> /dev/null; do - echo "Waiting for database to be ready ..." - sleep 5 -done ->&2 echo "Database is ready!" - -# Set DATABASE_URL env variable in correct format for application -export DATABASE_URL=postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/$POSTGRES_DATABASE_API - -# Run migrations -npm run db:migrate -npm run db:seed - -# Finally execute start command -exec $CMD diff --git a/scripts/wait-for-it.sh b/scripts/wait-for-it.sh new file mode 100755 index 00000000..b994078a --- /dev/null +++ b/scripts/wait-for-it.sh @@ -0,0 +1,83 @@ +#!/bin/sh + +# POSIX compatible clone of wait-for-it.sh +# This copy is from https://github.com/eficode/wait-for/commits/master +# at commit 8d9b4446 + +TIMEOUT=15 +QUIET=0 + +echoerr() { + if [ "$QUIET" -ne 1 ]; then printf "%s\n" "$*" 1>&2; fi +} + +usage() { + exitcode="$1" + cat << USAGE >&2 +Usage: + $cmdname host:port [-t timeout] [-- command args] + -q | --quiet Do not 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 "$exitcode" +} + +wait_for() { + echo "Wait $TIMEOUT seconds for $HOST:$PORT to be ready ..." + for i in `seq $TIMEOUT` ; do + nc -z "$HOST" "$PORT" > /dev/null 2>&1 + result=$? + if [ $result -eq 0 ] ; then + if [ $# -gt 0 ] ; then + exec "$@" + fi + exit 0 + fi + sleep 1 + done + echo "Operation timed out" >&2 + exit 1 +} + +while [ $# -gt 0 ] +do + case "$1" in + *:* ) + HOST=$(printf "%s\n" "$1"| cut -d : -f 1) + PORT=$(printf "%s\n" "$1"| cut -d : -f 2) + shift 1 + ;; + -q | --quiet) + QUIET=1 + shift 1 + ;; + -t) + TIMEOUT="$2" + if [ "$TIMEOUT" = "" ]; then break; fi + shift 2 + ;; + --timeout=*) + TIMEOUT="${1#*=}" + shift 1 + ;; + --) + shift + break + ;; + --help) + usage 0 + ;; + *) + echoerr "Unknown argument: $1" + usage 1 + ;; + esac +done + +if [ "$HOST" = "" -o "$PORT" = "" ]; then + echoerr "Error: you need to provide a host and port to test." + usage 2 +fi + +wait_for "$@"