Skip to content

Commit

Permalink
Add Dockerfile, circle.yml and ENTRYPOINT script
Browse files Browse the repository at this point in the history
- add Dockerfile
- add example.ini so docker container runs out of the box
- add shellscript as an ENTRYPOINT so container can be used like an
  executable
- add circle.yml for automated docker image building
  • Loading branch information
mostlygeek committed May 25, 2016
1 parent 2de95ce commit daf5cbb
Show file tree
Hide file tree
Showing 5 changed files with 224 additions and 3 deletions.
29 changes: 29 additions & 0 deletions Dockerfile
@@ -0,0 +1,29 @@
FROM python:2.7-alpine

WORKDIR /app

RUN addgroup -g 10001 app && \
adduser -D -u 10001 -G app -h /app -s /sbin/nologin app


# run the server by default
ENTRYPOINT ["/app/docker-entrypoint.sh"]
CMD ["server"]

# install / cache dependencies first
COPY requirements.txt /app/requirements.txt

# install depenencies, cleanup and add libstdc++ back in since
# we the app needs to link to it
RUN apk add --update build-base && \
pip install -r requirements.txt && \
apk del --purge build-base gcc && \
apk add libstdc++


# Copy in the whole app after dependencies have been installed & cached
COPY . /app
RUN python setup.py develop

# De-escalate from root privileges with app user
USER app
6 changes: 3 additions & 3 deletions README → README.md
@@ -1,6 +1,6 @@
===================================================
Storage Engine for Firefox Sync Server, version 1.5
===================================================
[![CircleCI](https://circleci.com/gh/mostlygeek/server-syncstorage.svg?style=svg)](https://circleci.com/gh/mostlygeek/server-syncstorage)

# Storage Engine for Firefox Sync Server, version 1.5

This is the storage engine for version 1.5 of the Firefox Sync Server.
It implements the API defined at:
Expand Down
65 changes: 65 additions & 0 deletions circle.yml
@@ -0,0 +1,65 @@
machine:
services:
- docker

dependencies:
cache_directories:
- "~/docker"

override:
- docker info

# Build the container, using Circle's Docker cache. Only use 1 image per
# day to keep the cache size down.
- I="image-$(date +%j).tgz"; if [[ -e ~/docker/$I ]]; then echo "Loading $I"; pigz -d -c ~/docker/$I | docker load; fi

# Create a version.json file for the app to serve; copy it to the CircleCI
# artifacts directory for debugging.
- >
printf '{"commit":"%s","version":"%s","source":"https://github.com/%s/%s","build":"%s"}\n'
"$CIRCLE_SHA1"
"$CIRCLE_TAG"
"$CIRCLE_PROJECT_USERNAME"
"$CIRCLE_PROJECT_REPONAME"
"$CIRCLE_BUILD_URL"
> version.json
- cp version.json $CIRCLE_ARTIFACTS

# build the actual deployment container
- docker build -t app:build .
- docker images --no-trunc | awk '/^app/ {print $3}' | tee $CIRCLE_ARTIFACTS/docker-image-shasum256.txt

# Clean up any old images; save the new one.
- I="image-$(date +%j).tgz"; mkdir -p ~/docker; rm ~/docker/*; docker save app:build | pigz --fast -c > ~/docker/$I; ls -l ~/docker

test:
override:
- docker run -it app:build test_flake8
- docker run -it app:build test_nose
- docker run -it app:build test_functional

# Tag and push the container to Docker Hub.
deployment:
# hub_all:
# branch: "/.*/"
# commands:
# - "[ ! -z $DOCKERHUB_REPO ]"
# - docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS
# - "docker tag app:build ${DOCKERHUB_REPO}:unstable"
# - "docker push ${DOCKERHUB_REPO}:unstable"
hub_latest:
branch: "master"
commands:
- "[ ! -z $DOCKERHUB_REPO ]"
- docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS
- "docker tag app:build ${DOCKERHUB_REPO}:latest"
- "docker push ${DOCKERHUB_REPO}:latest"
hub_releases:
tag: /.*/
commands:
- "[ ! -z $DOCKERHUB_REPO ]"
- docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS
- "docker tag app:build ${DOCKERHUB_REPO}:${CIRCLE_TAG}"
- "docker images"
- "docker push ${DOCKERHUB_REPO}:${CIRCLE_TAG}"

66 changes: 66 additions & 0 deletions docker-entrypoint.sh
@@ -0,0 +1,66 @@
#!/bin/sh

cd $(dirname $0)
case "$1" in
server)
_SETTINGS_FILE=${SYNC_SETTINGS_FILE:-"/app/example.ini"}

if [ ! -e $_SETTINGS_FILE ]; then
echo "Could not find ini file: $_SETTINGS_FILE"
exit 1
fi

echo "Starting gunicorn with config: $_SETTINGS_FILE"

exec gunicorn \
--paste "$_SETTINGS_FILE" \
--bind ${HOST-127.0.0.1}:${PORT-8000}\
--worker-class mozsvc.gunicorn_worker.MozSvcGeventWorker \
--timeout ${SYNC_TIMEOUT-600} \
--workers ${WEB_CONCURRENCY-1}\
--graceful-timeout ${SYNC_GRACEFUL_TIMEOUT-660}\
--max-requests ${SYNC_MAX_REQUESTS-5000}\
--log-config "$_SETTINGS_FILE"
;;

test_all)
$0 test_flake8
$0 test_nose
$0 test_functional
;;

test_flake8)
echo "test - flake8"
flake8 syncstorage
;;

test_nose)
echo "test - nose"
nosetests --verbose --nocapture syncstorage/tests
;;

test_functional)
echo "test - functional"
# run functional tests
export MOZSVC_SQLURI=sqlite:///:memory:
gunicorn --paste ./syncstorage/tests/tests.ini \
--workers 1 \
--worker-class mozsvc.gunicorn_worker.MozSvcGeventWorker &

SERVER_PID=$!
sleep 2

$0 test_endpoint http://localhost:5000

kill $SERVER_PID
;;

test_endpoint)
python syncstorage/tests/functional/test_storage.py $2
;;

*)
echo "Unknown CMD, $1"
exit 1
;;
esac
61 changes: 61 additions & 0 deletions example.ini
@@ -0,0 +1,61 @@
#
# example configuration with most options so docker container
# can run right out of the box
#

[server:main]
use = egg:Paste#http
host = 0.0.0.0
port = 9000

[app:main]
use = egg:SyncStorage

[loggers]
keys = root, gunicorn

[handlers]
keys = console

[formatters]
keys = generic

[logger_root]
level = INFO
handlers = console

[logger_gunicorn]
level = WARN
handlers = console
qualname = gunicorn

[handler_console]
class = StreamHandler
args = (sys.stdout,)
formatter = generic

[formatter_generic]
#class = mozsvc.util.JsonLogFormatter

[storage]
backend = syncstorage.storage.sql.SQLStorage

sqluri = sqlite:///:memory:
#sqluri = pymysql://user:pass@127.0.0.1/weave0

standard_collections = true
quota_size = 5242880
pool_size = 100
pool_recycle = 3600
reset_on_return = true
create_tables = true
batch_max_count = 4000

# memcache caching
#cache_servers = 127.0.0.1:11311
#cache_key_prefix = sync-storage
#cached_collections = meta clients
#cache_only_collections = tabs

[hawkauth]
secret = "secret value"

0 comments on commit daf5cbb

Please sign in to comment.