Deploying your site =================== GLAMkit is designed to be easily deployed and scaled using Docker. See :doc:`../topics/docker`. Your project's ``Dockerfile`` is used to prepare a Docker image. It looks something like:: FROM interaction/icekit:local WORKDIR /opt/project_template/ COPY package.json /opt/project_template/ RUN npm-install.sh && rm -rf /root/.npm ENV PATH=/opt/project_template/node_modules/.bin:$PATH COPY bower.json /opt/project_template/ RUN bower-install.sh && rm -rf /root/.cache/bower COPY requirements.txt /opt/project_template/ RUN pip install --no-cache-dir -r requirements.txt RUN md5sum requirements.txt > requirements.txt.md5 ENV ICEKIT_PROJECT_DIR=/opt/project_template COPY . /opt/project_template/ RUN manage.py collectstatic --noinput --verbosity=0 RUN manage.py compress --verbosity=0 When you build an image, Docker steps through the Dockerfile, following the instructions therein. Deploy a Demo to Docker Cloud ----------------------------- Use the Deploy to Docker Cloud button to create a new default GLAMkit stack on `Docker Cloud`_. .. image:: https://files.cloud.docker.com/images/deploy-to-dockercloud.svg :target: https://cloud.docker.com/stack/deploy/?repo=https://github.com/ic-labs/django-icekit/ :alt: Deploy to Docker Cloud (This is mostly for testing and demonstration purposes - you won't be able to customise your project when deploying the official GLAMkit Docker image this way.) .. TODO: document how to deploy your own project for the first time. Deploying your project for the first time ----------------------------------------- This section is a summary of the `Docker getting started `__ instructions. The process of deploying a site for the first time is: 0. Create a `Docker Hub `__ account. You can use this for all the official Docker services, including Docker Cloud. 1. Build and tag an image from your Dockerfile:: docker build -t "$DOCKER_ID_USER/$PROJECT_NAME:master" You can use anything instead of "master" here - we recommend using the name of the git branch you use for production deployments. 2. Push the image to Docker Hub:: docker push "$DOCKER_ID_USER/$PROJECT_NAME:master" It should now appear in the ``Repositories`` section on Docker Cloud. 3. Set up a new stack in Docker Cloud. This needs more documentation (see the `Docker Cloud docs `__ for more). For now, here's a sample production stackfile:: django: environment: - AWS_ACCESS_KEY_ID=... - AWS_SECRET_ACCESS_KEY=... - AWS_STORAGE_BUCKET_NAME=... - BASE_SETTINGS_MODULE=production - EMAIL_HOST=... - EMAIL_HOST_PASSWORD=... - EMAIL_HOST_USER=... - FORCE_SSL=yes - PGHOST=... - PGPASSWORD=... - PGUSER=... - PYTHONWARNINGS=ignore - 'SECRET_KEY=...' - SITE_DOMAIN=www.mydomain.com.au - 'VIRTUAL_HOST=www.domain.com.au,https://www.mydomain.com.au' expose: - '8080' image: '$DOCKER_ID_USER/$PROJECT_NAME:master' links: - elasticsearch - redis restart: on-failure sequential_deployment: true tags: - production volumes: - /opt/$PROJECT_NAME/var elasticsearch: image: 'interaction/elasticsearch-icu:1' restart: on-failure tags: - production redis: command: redis-server --appendonly yes image: 'redis:3-alpine' restart: on-failure tags: - production target_num_containers: 2 Subsequent deployments ---------------------- When you want to release an update to your site, we suggest following these steps: 1. Build your code into a Docker Image. 2. Ensure that tests run on the Docker Image. 3. Push the Image to Docker Hub. 4. Deploy the Image using Docker Cloud. 5. Check it worked (view some key pages). Automating releases with Travis and Docker Cloud ------------------------------------------------ In Travis ~~~~~~~~~ A Continuous Integration service like `Travis `__ can run tests and other commands automatically for every pushed revision. The project template includes a ``.travis.yml`` file which instructs Travis to build the Docker image, run tests on the built image, and if the tests pass, to push the image to Docker Hub. In Docker Cloud ~~~~~~~~~~~~~~~ You can set ``autoredeploy: true`` in your Docker Cloud stackfile to automatically redeploy services when their Docker images are updated. Here's an excerpt from a stackfile, which auto-redeploys when your ``{docker_hub_account}/{image_name}:{tag}`` image is updated (e.g. ``interaction/acmi:staging`` ) :: django: autoredeploy: true image: '{docker_hub_account}/{image_name}:{tag}' ... elasticsearch: ... redis: ... Fixing a broken deployment -------------------------- There are any number of reasons why a deployment can break. Assuming your app is unreachable, the best place to start is by looking at the logs in Docker Cloud. You can also restart and redeploy the services using the Docker Cloud tools. Rolling back a deployment ~~~~~~~~~~~~~~~~~~~~~~~~~ `(You almost never want to do this -- the consistency of Docker and a good git workflow makes it easy to check whether a deployment will break well before it hits the production server.)` First, identify the revision you want to roll back to. Depending on your git workflow, this will either be the last merge to the production branch, or the last release tag, or you may need to guess. This is your target revision. Rolling back the data ````````````````````` The main difficulty in rolling back is whether any Django migrations were applied between the new/breaking release and the target revision, and whether those migrations can be reversed. If migrations have been applied, it's probably still going to be quicker and less messyto fix the deployment or restore a database backup than to roll back migrations. Further, if any migrations don't have a ``reverse()`` operation specified, then they can't be rolled back, and you'll either have to restore from a database backup, improvise a ``reverse()`` operation, or do nothing and hope the target revision is compatible enough to work. If you're still determined to roll back the migrations, compare the breaking and target revisions to see if any migrations were added to the codebase. If so, then you must manually apply those migrations in reverse using:: manage.py migrate {app} {4-digit migration number to reverse minus 1, or 'zero'} Rolling back code ````````````````` After you've rolled back migrations, update the Docker Cloud stack file and change ``master`` tag to a full commit hash of the target release (you can get it from Travis build history) and click redeploy. That was fun ```````````` When the dust has settled, consider how to modify your process to avoid the need to roll back deployments. We sugges: - Use Docker for consistent, repeatable server environments - Use a git-flow-based branching workflow for careful separation of features from main branches - Write tests, and never deploy unless unit tests pass. - Deploy release candidates to a staging environment first, which has recent copies of production data and media. - Deploy all of staging to production, not just the features that passed tests.