diff --git a/command_cheat_sheet.md b/command_cheat_sheet.md new file mode 100644 index 0000000..c152b20 --- /dev/null +++ b/command_cheat_sheet.md @@ -0,0 +1,18 @@ +# Create a test NFS volume +# make sure the permissions on the NFS volume don't map to a user that can't access them +docker volume create --driver local --opt type=nfs --opt o=addr=nas1.androiddrew.com,rw --opt device=:/volume1/expanse nfs-test + +docker run --name test-postgres -v nfs-test:/var/lib/postgresql/data -d postgres:10.4-alpine + + +# Build a docker machine and push it to the docker hub + +## First set the docker env back to the local Host + +eval $(docker-machine env -u) + +## build with the tag using the docker file and the path + +docker build -t androiddrew/flask-docker-swarm_web:latest -f ./services/web/Dockerfile ./services/web + +docker push androiddrew/flask-docker-swarm_web:latest diff --git a/docker-compose-swarm.yml b/docker-compose-swarm.yml new file mode 100644 index 0000000..7b03c17 --- /dev/null +++ b/docker-compose-swarm.yml @@ -0,0 +1,105 @@ +# Image: Instead of referencing the local build directory, we are now using an image to set the context +# Deploy: We added a deploy keyword to configure the number of replicas, restart_policy, and placement contstraints for each service +# REFERENCE: https://docs.docker.com/compose/compose-file/ + +version: '3.6' + +services: + + web: + image: androiddrew/flask-docker-swarm_web:latest + deploy: + replicas: 1 + restart_policy: + condition: on-failure + placement: + constraints: [node.role == worker] + expose: + - 5000 + environment: + - FLASK_ENV=production + - APP_SETTINGS=project.config.ProductionConfig + - DB_USER=postgres + - DB_PASSWORD=postgres + # - SECRET_CODE=myprecious + # here we are going to use docker secrets to keep everything safe + #see the secrets section below + secrets: + - secret_code + depends_on: + - db + networks: + - app + # We can add a health check to either a conmpose file or Dockerfile https://docs.docker.com/engine/reference/builder/#healthcheck + healthcheck: + # Test is the actual command that will be run to check the health status + # It should return 0 (Healthy) or 1 (Unhealthy) + test: curl --fail http://localhost:5000/ping || exit 1 + interval: 10s + timeout: 2s + retries: 5 + + db: + image: androiddrew/flask-docker-swarm_db:latest + deploy: + replicas: 1 + restart_policy: + condition: on-failure + placement: + #constraints: [node.role == manager] + constraints: [node.role == worker] + volumes: + - data-volume:/var/lib/postgresql/data + expose: + - 5432 + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + networks: + - app + + nginx: + image: androiddrew/flask-docker-swarm_nginx:latest + deploy: + replicas: 1 + restart_policy: + condition: on-failure + placement: + constraints: [node.role == worker] + ports: + - 80:80 + depends_on: + - web + networks: + - app + + visualizer: + image: dockersamples/visualizer:latest + ports: + - 8080:8080 + volumes: + - "/var/run/docker.sock:/var/run/docker.sock" + deploy: + placement: + constraints: [node.role == manager] + networks: + - app + +# We are now using an overlay network to connect multiple Docker engines across each host and enable communication between Swarm services +networks: + app: + driver: overlay + +volumes: + #data-volume: + # driver: local + data-volume: + driver: local + driver_opts: + type: nfs + o: addr=nas1.androiddrew.com,rw + device: ":/volume1/expanse/flask_data" +# Secrets can be configured in either external or file-based manner +secrets: + secret_code: + external: true diff --git a/services/web/project/api/main.py b/services/web/project/api/main.py index 9edd847..230f58a 100644 --- a/services/web/project/api/main.py +++ b/services/web/project/api/main.py @@ -5,7 +5,9 @@ from flask import Blueprint, jsonify, request LOGGER = logging.getLogger('gunicorn.error') -SECRET_CODE = os.environ.get('SECRET_CODE') +#SECRET_CODE = os.environ.get('SECRET_CODE') +# Here we are accessing the secret_code set by the external config in our docker-compose file +SECRET_CODE = open('/run/secrets/secret_code').read().strip() main_blueprint = Blueprint('main', __name__)