├── .gitignore └── Lesson-Files ├── 01-Docker-Basics ├── 00-Starter-Code │ └── dev1 │ │ └── app │ │ ├── app.py │ │ └── requirements.txt ├── 01-Bind-Mounts │ └── dev1 │ │ └── app │ │ ├── app.py │ │ ├── requirements.txt │ │ └── run.sh ├── 01-Hello-Dockerfile │ └── dev1 │ │ ├── Dockerfile │ │ ├── app │ │ ├── app.py │ │ └── requirements.txt │ │ ├── dev1 │ │ ├── dev2 │ │ └── dev3 └── 02-Dockerfile-Optimize │ └── dev1 │ ├── Dockerfile │ ├── app │ ├── app.py │ └── requirements.txt │ ├── dev1 │ ├── dev2 │ ├── dev3 │ ├── dev4 │ └── test.txt ├── 02-Docker-Compose ├── 01-Hello-Compose │ ├── dev1 │ │ ├── Dockerfile │ │ └── app │ │ │ ├── app.py │ │ │ └── requirements.txt │ └── docker-compose.yml ├── 02-Named-Volume │ ├── dev1 │ │ ├── Dockerfile │ │ └── app │ │ │ ├── app.py │ │ │ └── requirements.txt │ └── docker-compose.yml ├── 03-Node-Red │ ├── dev1 │ │ ├── Dockerfile │ │ └── app │ │ │ ├── app.py │ │ │ └── requirements.txt │ └── docker-compose.yml ├── 04-Node-Red-Config │ ├── dev1 │ │ ├── Dockerfile │ │ └── app │ │ │ ├── app.py │ │ │ └── requirements.txt │ ├── docker-compose.yml │ └── nodered │ │ ├── Dockerfile │ │ └── flows.json ├── 05-Node-Red-Config-Part-2 │ ├── dev1 │ │ ├── Dockerfile │ │ └── app │ │ │ ├── app.py │ │ │ └── requirements.txt │ ├── docker-compose.yml │ └── nodered │ │ ├── Dockerfile │ │ └── flows.json ├── 06-InfluxDB │ ├── dev1 │ │ ├── Dockerfile │ │ └── app │ │ │ ├── app.py │ │ │ └── requirements.txt │ ├── docker-compose.yml │ └── nodered │ │ ├── Dockerfile │ │ └── flows.json ├── 07-InfluxDB-config │ ├── dev1 │ │ ├── Dockerfile │ │ └── app │ │ │ ├── app.py │ │ │ └── requirements.txt │ ├── docker-compose.yml │ └── nodered │ │ ├── Dockerfile │ │ └── flows.json ├── 08-InfluxDB-Healthcheck │ ├── dev1 │ │ ├── Dockerfile │ │ └── app │ │ │ ├── app.py │ │ │ └── requirements.txt │ ├── docker-compose.yml │ ├── influxdb │ │ └── Dockerfile │ └── nodered │ │ ├── Dockerfile │ │ └── flows.json ├── 09-Influxdb-nodered-automation │ ├── dev1 │ │ ├── Dockerfile │ │ └── app │ │ │ ├── app.py │ │ │ └── requirements.txt │ ├── docker-compose.yml │ ├── influxdb │ │ └── Dockerfile │ ├── nodered.1 │ │ ├── Dockerfile │ │ ├── flows.json │ │ ├── flows_cred.json │ │ └── settings.js │ └── nodered │ │ ├── Dockerfile │ │ ├── flows.json │ │ ├── flows_cred.json │ │ └── settings.js ├── 10-nodered-credentials │ ├── dev1 │ │ ├── Dockerfile │ │ └── app │ │ │ ├── app.py │ │ │ └── requirements.txt │ ├── docker-compose.yml │ ├── influxdb │ │ └── Dockerfile │ └── nodered │ │ ├── Dockerfile │ │ ├── flows.json │ │ ├── flows_cred.json │ │ └── settings.js ├── 11-Grafana │ ├── dev1 │ │ ├── Dockerfile │ │ └── app │ │ │ ├── app.py │ │ │ └── requirements.txt │ ├── docker-compose.yml │ ├── influxdb │ │ └── Dockerfile │ └── nodered │ │ ├── Dockerfile │ │ ├── flows.json │ │ ├── flows_cred.json │ │ └── settings.js ├── 12-Grafana-Config │ ├── dev1 │ │ ├── Dockerfile │ │ └── app │ │ │ ├── app.py │ │ │ └── requirements.txt │ ├── docker-compose.yml │ ├── influxdb │ │ └── Dockerfile │ └── nodered │ │ ├── Dockerfile │ │ ├── flows.json │ │ ├── flows_cred.json │ │ └── settings.js ├── 13-Grafana-Automation │ ├── dev1 │ │ ├── Dockerfile │ │ └── app │ │ │ ├── app.py │ │ │ └── requirements.txt │ ├── docker-compose.yml │ ├── ds.txt │ ├── grafana │ │ ├── Dockerfile │ │ ├── dashboards │ │ │ ├── dashboard.json │ │ │ ├── dashboard.json.old │ │ │ └── dashboard.yml │ │ └── datasource.yml │ ├── influxdb │ │ └── Dockerfile │ └── nodered │ │ ├── Dockerfile │ │ ├── flows.json │ │ ├── flows_cred.json │ │ └── settings.js ├── 14-Postgres │ ├── dev1 │ │ ├── Dockerfile │ │ └── app │ │ │ ├── app.py │ │ │ └── requirements.txt │ ├── docker-compose.yml │ ├── grafana │ │ ├── Dockerfile │ │ ├── dashboards │ │ │ ├── dashboard.json │ │ │ └── dashboard.yml │ │ └── datasource.yml │ ├── influxdb │ │ └── Dockerfile │ ├── nodered │ │ ├── Dockerfile │ │ ├── flows.json │ │ ├── flows_cred.json │ │ └── settings.js │ └── postgres │ │ └── Dockerfile ├── 15-Postgres-Schema │ ├── dev1 │ │ ├── Dockerfile │ │ └── app │ │ │ ├── app.py │ │ │ └── requirements.txt │ ├── docker-compose.yml │ ├── grafana │ │ ├── Dockerfile │ │ ├── dashboards │ │ │ ├── dashboard.json │ │ │ └── dashboard.yml │ │ └── datasource.yml │ ├── influxdb │ │ └── Dockerfile │ ├── nodered │ │ ├── Dockerfile │ │ ├── flows.json │ │ ├── flows_cred.json │ │ └── settings.js │ └── postgres │ │ ├── Dockerfile │ │ └── schema.sql ├── 16-PostgREST │ ├── dev1 │ │ ├── Dockerfile │ │ └── app │ │ │ ├── app.py │ │ │ └── requirements.txt │ ├── docker-compose.yml │ ├── grafana │ │ ├── Dockerfile │ │ ├── dashboards │ │ │ ├── dashboard.json │ │ │ └── dashboard.yml │ │ └── datasource.yml │ ├── influxdb │ │ └── Dockerfile │ ├── nodered │ │ ├── Dockerfile │ │ ├── flows.json │ │ ├── flows_cred.json │ │ └── settings.js │ └── postgres │ │ ├── Dockerfile │ │ └── schema.sql ├── 17-PostgREST-NodeRED │ ├── dev1 │ │ ├── Dockerfile │ │ └── app │ │ │ ├── app.py │ │ │ └── requirements.txt │ ├── docker-compose.yml │ ├── grafana │ │ ├── Dockerfile │ │ ├── dashboards │ │ │ ├── dashboard.json │ │ │ └── dashboard.yml │ │ └── datasource.yml │ ├── influxdb │ │ └── Dockerfile │ ├── nodered │ │ ├── Dockerfile │ │ ├── flows.json │ │ ├── flows_cred.json │ │ └── settings.js │ └── postgres │ │ ├── Dockerfile │ │ └── schema.sql ├── 18-Grafana-Postgres │ ├── dev1 │ │ ├── Dockerfile │ │ └── app │ │ │ ├── app.py │ │ │ └── requirements.txt │ ├── docker-compose.yml │ ├── grafana │ │ ├── Dockerfile │ │ ├── dashboards │ │ │ ├── dashboard.json │ │ │ ├── dashboard.json.old │ │ │ └── dashboard.yml │ │ └── datasource.yml │ ├── influxdb │ │ └── Dockerfile │ ├── nodered │ │ ├── Dockerfile │ │ ├── flows.json │ │ ├── flows_cred.json │ │ └── settings.js │ └── postgres │ │ ├── Dockerfile │ │ └── schema.sql ├── 19-Docker-Networking │ ├── dev1 │ │ ├── Dockerfile │ │ └── app │ │ │ ├── app.py │ │ │ └── requirements.txt │ ├── docker-compose.yml │ ├── grafana │ │ ├── Dockerfile │ │ ├── dashboards │ │ │ ├── dashboard.json │ │ │ ├── dashboard.json.old │ │ │ └── dashboard.yml │ │ └── datasource.yml │ ├── influxdb │ │ └── Dockerfile │ ├── nodered │ │ ├── Dockerfile │ │ ├── flows.json │ │ ├── flows_cred.json │ │ └── settings.js │ └── postgres │ │ ├── Dockerfile │ │ └── schema.sql └── 20-Docker-Compose-Exec │ ├── dev1 │ ├── Dockerfile │ └── app │ │ ├── app.py │ │ └── requirements.txt │ ├── docker-compose.yml │ ├── grafana │ ├── Dockerfile │ ├── dashboards │ │ ├── dashboard.json │ │ ├── dashboard.json.old │ │ └── dashboard.yml │ └── datasource.yml │ ├── influxdb │ └── Dockerfile │ ├── nodered │ ├── Dockerfile │ ├── flows.json │ ├── flows_cred.json │ └── settings.js │ └── postgres │ ├── Dockerfile │ └── schema.sql └── 04-Docker-Admin ├── 01-VPN-Setup ├── dev1 │ ├── .gitlab-ci.yml │ ├── Dockerfile │ ├── app │ │ ├── app.py │ │ └── requirements.txt │ └── gitinit.sh ├── docker-compose.yml ├── grafana │ ├── Dockerfile │ ├── dashboards │ │ ├── dashboard.json │ │ ├── dashboard.json.old │ │ └── dashboard.yml │ └── datasource.yml ├── influxdb │ └── Dockerfile ├── nodered │ ├── Dockerfile │ ├── flows.json │ ├── flows_cred.json │ └── settings.js └── postgres │ ├── Dockerfile │ └── schema.sql ├── 02-Linux-Capabilities ├── dev1 │ ├── .gitlab-ci.yml │ ├── Dockerfile │ ├── app │ │ ├── app.py │ │ └── requirements.txt │ └── gitinit.sh ├── docker-compose.yml ├── grafana │ ├── Dockerfile │ ├── dashboards │ │ ├── dashboard.json │ │ ├── dashboard.json.old │ │ └── dashboard.yml │ └── datasource.yml ├── influxdb │ └── Dockerfile ├── nodered │ ├── Dockerfile │ ├── flows.json │ ├── flows_cred.json │ └── settings.js └── postgres │ ├── Dockerfile │ └── schema.sql ├── 03-Connecting-to-VPN ├── dev1 │ ├── .gitlab-ci.yml │ ├── Dockerfile │ ├── app │ │ ├── app.py │ │ └── requirements.txt │ └── gitinit.sh ├── docker-compose.yml ├── grafana │ ├── Dockerfile │ ├── dashboards │ │ ├── dashboard.json │ │ ├── dashboard.json.old │ │ └── dashboard.yml │ └── datasource.yml ├── influxdb │ └── Dockerfile ├── nodered │ ├── Dockerfile │ ├── flows.json │ ├── flows_cred.json │ └── settings.js └── postgres │ ├── Dockerfile │ └── schema.sql ├── 04-service_mode ├── dev1 │ ├── .gitlab-ci.yml │ ├── Dockerfile │ ├── app │ │ ├── app.py │ │ └── requirements.txt │ └── gitinit.sh ├── docker-compose.yml ├── grafana │ ├── Dockerfile │ ├── dashboards │ │ ├── dashboard.json │ │ ├── dashboard.json.old │ │ └── dashboard.yml │ └── datasource.yml ├── influxdb │ └── Dockerfile ├── nodered │ ├── Dockerfile │ ├── flows.json │ ├── flows_cred.json │ └── settings.js └── postgres │ ├── Dockerfile │ └── schema.sql └── 05-Rest-of-Stack ├── dev1 ├── .gitlab-ci.yml ├── Dockerfile ├── app │ ├── app.py │ └── requirements.txt └── gitinit.sh ├── docker-compose.yml ├── grafana ├── Dockerfile ├── dashboards │ ├── dashboard.json │ ├── dashboard.json.old │ └── dashboard.yml └── datasource.yml ├── influxdb └── Dockerfile ├── nodered ├── Dockerfile ├── flows.json ├── flows_cred.json └── settings.js └── postgres ├── Dockerfile └── schema.sql /.gitignore: -------------------------------------------------------------------------------- 1 | *.pem 2 | scripts/ 3 | -------------------------------------------------------------------------------- /Lesson-Files/01-Docker-Basics/00-Starter-Code/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"name" : os.getenv('HOSTNAME') ,"temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/01-Docker-Basics/00-Starter-Code/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/01-Docker-Basics/01-Bind-Mounts/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"name" : os.getenv('HOSTNAME') ,"temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/01-Docker-Basics/01-Bind-Mounts/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/01-Docker-Basics/01-Bind-Mounts/dev1/app/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | pip install -r requirements.txt && 3 | python app.py -------------------------------------------------------------------------------- /Lesson-Files/01-Docker-Basics/01-Hello-Dockerfile/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | COPY ./app/ /app 10 | 11 | EXPOSE 5000 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | CMD [ "app.py", "--host", "0.0.0.0" ] 16 | 17 | -------------------------------------------------------------------------------- /Lesson-Files/01-Docker-Basics/01-Hello-Dockerfile/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"name" : os.getenv('HOSTNAME') ,"temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/01-Docker-Basics/01-Hello-Dockerfile/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/01-Docker-Basics/01-Hello-Dockerfile/dev1/dev1: -------------------------------------------------------------------------------- 1 | IMAGE CREATED CREATED BY SIZE COMMENT 2 | fbb3a0b1d250 39 seconds ago /bin/sh -c #(nop) CMD ["app.py" "--host" "0… 0B 3 | d5fb45523733 39 seconds ago /bin/sh -c #(nop) ENTRYPOINT ["python"] 0B 4 | c5e0972bc889 39 seconds ago /bin/sh -c #(nop) EXPOSE 5000 0B 5 | 7c7555751e5f 39 seconds ago /bin/sh -c pip install -r requirements.txt 11.1MB 6 | 5ad8078f1514 45 seconds ago /bin/sh -c #(nop) WORKDIR /app 0B 7 | d12d11eed4bb 45 seconds ago /bin/sh -c #(nop) COPY dir:717deea22fa9dbd3e… 397B 8 | d6f5dddc84ee 4 days ago /bin/sh -c #(nop) CMD ["python3"] 0B 9 | 4 days ago /bin/sh -c set -ex; wget -O get-pip.py "$P… 8.01MB 10 | 4 days ago /bin/sh -c #(nop) ENV PYTHON_GET_PIP_SHA256… 0B 11 | 4 days ago /bin/sh -c #(nop) ENV PYTHON_GET_PIP_URL=ht… 0B 12 | 4 days ago /bin/sh -c #(nop) ENV PYTHON_PIP_VERSION=21… 0B 13 | 4 days ago /bin/sh -c cd /usr/local/bin && ln -s idle3… 32B 14 | 4 days ago /bin/sh -c set -ex && wget -O python.tar.x… 55.8MB 15 | 4 days ago /bin/sh -c #(nop) ENV PYTHON_VERSION=3.9.4 0B 16 | 9 days ago /bin/sh -c #(nop) ENV GPG_KEY=E3FF2839C048B… 0B 17 | 9 days ago /bin/sh -c apt-get update && apt-get install… 18MB 18 | 9 days ago /bin/sh -c #(nop) ENV LANG=C.UTF-8 0B 19 | 9 days ago /bin/sh -c #(nop) ENV PATH=/usr/local/bin:/… 0B 20 | 9 days ago /bin/sh -c set -ex; apt-get update; apt-ge… 510MB 21 | 9 days ago /bin/sh -c apt-get update && apt-get install… 146MB 22 | 9 days ago /bin/sh -c set -ex; if ! command -v gpg > /… 17.5MB 23 | 9 days ago /bin/sh -c set -eux; apt-get update; apt-g… 16.5MB 24 | 9 days ago /bin/sh -c #(nop) CMD ["bash"] 0B 25 | 9 days ago /bin/sh -c #(nop) ADD file:c254898ceb4172f05… 114MB 26 | -------------------------------------------------------------------------------- /Lesson-Files/01-Docker-Basics/01-Hello-Dockerfile/dev1/dev2: -------------------------------------------------------------------------------- 1 | IMAGE CREATED CREATED BY SIZE COMMENT 2 | fbb3a0b1d250 About a minute ago /bin/sh -c #(nop) CMD ["app.py" "--host" "0… 0B 3 | d5fb45523733 About a minute ago /bin/sh -c #(nop) ENTRYPOINT ["python"] 0B 4 | c5e0972bc889 About a minute ago /bin/sh -c #(nop) EXPOSE 5000 0B 5 | 7c7555751e5f About a minute ago /bin/sh -c pip install -r requirements.txt 11.1MB 6 | 5ad8078f1514 About a minute ago /bin/sh -c #(nop) WORKDIR /app 0B 7 | d12d11eed4bb About a minute ago /bin/sh -c #(nop) COPY dir:717deea22fa9dbd3e… 397B 8 | d6f5dddc84ee 4 days ago /bin/sh -c #(nop) CMD ["python3"] 0B 9 | 4 days ago /bin/sh -c set -ex; wget -O get-pip.py "$P… 8.01MB 10 | 4 days ago /bin/sh -c #(nop) ENV PYTHON_GET_PIP_SHA256… 0B 11 | 4 days ago /bin/sh -c #(nop) ENV PYTHON_GET_PIP_URL=ht… 0B 12 | 4 days ago /bin/sh -c #(nop) ENV PYTHON_PIP_VERSION=21… 0B 13 | 4 days ago /bin/sh -c cd /usr/local/bin && ln -s idle3… 32B 14 | 4 days ago /bin/sh -c set -ex && wget -O python.tar.x… 55.8MB 15 | 4 days ago /bin/sh -c #(nop) ENV PYTHON_VERSION=3.9.4 0B 16 | 9 days ago /bin/sh -c #(nop) ENV GPG_KEY=E3FF2839C048B… 0B 17 | 9 days ago /bin/sh -c apt-get update && apt-get install… 18MB 18 | 9 days ago /bin/sh -c #(nop) ENV LANG=C.UTF-8 0B 19 | 9 days ago /bin/sh -c #(nop) ENV PATH=/usr/local/bin:/… 0B 20 | 9 days ago /bin/sh -c set -ex; apt-get update; apt-ge… 510MB 21 | 9 days ago /bin/sh -c apt-get update && apt-get install… 146MB 22 | 9 days ago /bin/sh -c set -ex; if ! command -v gpg > /… 17.5MB 23 | 9 days ago /bin/sh -c set -eux; apt-get update; apt-g… 16.5MB 24 | 9 days ago /bin/sh -c #(nop) CMD ["bash"] 0B 25 | 9 days ago /bin/sh -c #(nop) ADD file:c254898ceb4172f05… 114MB 26 | -------------------------------------------------------------------------------- /Lesson-Files/01-Docker-Basics/01-Hello-Dockerfile/dev1/dev3: -------------------------------------------------------------------------------- 1 | IMAGE CREATED CREATED BY SIZE COMMENT 2 | eba65633fb22 43 seconds ago /bin/sh -c #(nop) CMD ["app.py" "--host" "0… 0B 3 | 34e45569e040 44 seconds ago /bin/sh -c #(nop) ENTRYPOINT ["python"] 0B 4 | bf4eda7483bf 44 seconds ago /bin/sh -c #(nop) EXPOSE 5000 0B 5 | b16273066a56 44 seconds ago /bin/sh -c pip install -r requirements.txt 11.1MB 6 | 1aab77ae1969 51 seconds ago /bin/sh -c #(nop) WORKDIR /app 0B 7 | 838417e5c99a 51 seconds ago /bin/sh -c #(nop) COPY dir:2f76f2b892c9fa5dc… 397B 8 | d6f5dddc84ee 4 days ago /bin/sh -c #(nop) CMD ["python3"] 0B 9 | 4 days ago /bin/sh -c set -ex; wget -O get-pip.py "$P… 8.01MB 10 | 4 days ago /bin/sh -c #(nop) ENV PYTHON_GET_PIP_SHA256… 0B 11 | 4 days ago /bin/sh -c #(nop) ENV PYTHON_GET_PIP_URL=ht… 0B 12 | 4 days ago /bin/sh -c #(nop) ENV PYTHON_PIP_VERSION=21… 0B 13 | 4 days ago /bin/sh -c cd /usr/local/bin && ln -s idle3… 32B 14 | 4 days ago /bin/sh -c set -ex && wget -O python.tar.x… 55.8MB 15 | 4 days ago /bin/sh -c #(nop) ENV PYTHON_VERSION=3.9.4 0B 16 | 9 days ago /bin/sh -c #(nop) ENV GPG_KEY=E3FF2839C048B… 0B 17 | 9 days ago /bin/sh -c apt-get update && apt-get install… 18MB 18 | 9 days ago /bin/sh -c #(nop) ENV LANG=C.UTF-8 0B 19 | 9 days ago /bin/sh -c #(nop) ENV PATH=/usr/local/bin:/… 0B 20 | 9 days ago /bin/sh -c set -ex; apt-get update; apt-ge… 510MB 21 | 9 days ago /bin/sh -c apt-get update && apt-get install… 146MB 22 | 9 days ago /bin/sh -c set -ex; if ! command -v gpg > /… 17.5MB 23 | 9 days ago /bin/sh -c set -eux; apt-get update; apt-g… 16.5MB 24 | 9 days ago /bin/sh -c #(nop) CMD ["bash"] 0B 25 | 9 days ago /bin/sh -c #(nop) ADD file:c254898ceb4172f05… 114MB 26 | -------------------------------------------------------------------------------- /Lesson-Files/01-Docker-Basics/02-Dockerfile-Optimize/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:slim 2 | 3 | # ensure i mention why this is important...layers 4 | COPY ./app/requirements.txt /app/requirements.txt 5 | 6 | WORKDIR /app 7 | 8 | RUN pip install -r requirements.txt 9 | 10 | COPY ./app/ /app 11 | 12 | EXPOSE 5000 13 | 14 | ENTRYPOINT [ "python" ] 15 | 16 | CMD [ "app.py", "--host", "0.0.0.0" ] 17 | 18 | -------------------------------------------------------------------------------- /Lesson-Files/01-Docker-Basics/02-Dockerfile-Optimize/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"name" : os.getenv('HOSTNAME') ,"temp" : random.randrange(-10, 21, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/01-Docker-Basics/02-Dockerfile-Optimize/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/01-Docker-Basics/02-Dockerfile-Optimize/dev1/dev1: -------------------------------------------------------------------------------- 1 | IMAGE CREATED CREATED BY SIZE COMMENT 2 | 6df324a431d4 47 seconds ago /bin/sh -c #(nop) CMD ["app.py" "--host" "0… 0B 3 | aab48611a08b 47 seconds ago /bin/sh -c #(nop) ENTRYPOINT ["python"] 0B 4 | cd099b76241b 47 seconds ago /bin/sh -c #(nop) EXPOSE 5000 0B 5 | 01f4caeda724 48 seconds ago /bin/sh -c #(nop) COPY dir:2f76f2b892c9fa5dc… 397B 6 | f01c93c7d260 48 seconds ago /bin/sh -c pip install -r requirements.txt 11.1MB 7 | 83fe5948e47f 54 seconds ago /bin/sh -c #(nop) WORKDIR /app 0B 8 | 3e9689d9edb5 54 seconds ago /bin/sh -c #(nop) COPY file:430e8697ad5d9784… 14B 9 | d6f5dddc84ee 4 days ago /bin/sh -c #(nop) CMD ["python3"] 0B 10 | 4 days ago /bin/sh -c set -ex; wget -O get-pip.py "$P… 8.01MB 11 | 4 days ago /bin/sh -c #(nop) ENV PYTHON_GET_PIP_SHA256… 0B 12 | 4 days ago /bin/sh -c #(nop) ENV PYTHON_GET_PIP_URL=ht… 0B 13 | 4 days ago /bin/sh -c #(nop) ENV PYTHON_PIP_VERSION=21… 0B 14 | 4 days ago /bin/sh -c cd /usr/local/bin && ln -s idle3… 32B 15 | 4 days ago /bin/sh -c set -ex && wget -O python.tar.x… 55.8MB 16 | 4 days ago /bin/sh -c #(nop) ENV PYTHON_VERSION=3.9.4 0B 17 | 9 days ago /bin/sh -c #(nop) ENV GPG_KEY=E3FF2839C048B… 0B 18 | 9 days ago /bin/sh -c apt-get update && apt-get install… 18MB 19 | 9 days ago /bin/sh -c #(nop) ENV LANG=C.UTF-8 0B 20 | 9 days ago /bin/sh -c #(nop) ENV PATH=/usr/local/bin:/… 0B 21 | 9 days ago /bin/sh -c set -ex; apt-get update; apt-ge… 510MB 22 | 9 days ago /bin/sh -c apt-get update && apt-get install… 146MB 23 | 9 days ago /bin/sh -c set -ex; if ! command -v gpg > /… 17.5MB 24 | 9 days ago /bin/sh -c set -eux; apt-get update; apt-g… 16.5MB 25 | 9 days ago /bin/sh -c #(nop) CMD ["bash"] 0B 26 | 9 days ago /bin/sh -c #(nop) ADD file:c254898ceb4172f05… 114MB 27 | -------------------------------------------------------------------------------- /Lesson-Files/01-Docker-Basics/02-Dockerfile-Optimize/dev1/dev2: -------------------------------------------------------------------------------- 1 | IMAGE CREATED CREATED BY SIZE COMMENT 2 | ce274ca5caa0 8 minutes ago /bin/sh -c #(nop) CMD ["app.py" "--host" "0… 0B 3 | b606afdc5811 8 minutes ago /bin/sh -c #(nop) ENTRYPOINT ["python"] 0B 4 | 89d6f2681c2e 8 minutes ago /bin/sh -c #(nop) EXPOSE 5000 0B 5 | fdeb30cc35e5 8 minutes ago /bin/sh -c #(nop) COPY dir:2f76f2b892c9fa5dc… 397B 6 | 8d1a446b4fbd 9 minutes ago /bin/sh -c pip install -r requirements.txt 11.1MB 7 | 1ce596cc8ea3 9 minutes ago /bin/sh -c #(nop) WORKDIR /app 0B 8 | a3c2bd5ef1b5 9 minutes ago /bin/sh -c #(nop) COPY file:430e8697ad5d9784… 14B 9 | d6f5dddc84ee 4 days ago /bin/sh -c #(nop) CMD ["python3"] 0B 10 | 4 days ago /bin/sh -c set -ex; wget -O get-pip.py "$P… 8.01MB 11 | 4 days ago /bin/sh -c #(nop) ENV PYTHON_GET_PIP_SHA256… 0B 12 | 4 days ago /bin/sh -c #(nop) ENV PYTHON_GET_PIP_URL=ht… 0B 13 | 4 days ago /bin/sh -c #(nop) ENV PYTHON_PIP_VERSION=21… 0B 14 | 4 days ago /bin/sh -c cd /usr/local/bin && ln -s idle3… 32B 15 | 4 days ago /bin/sh -c set -ex && wget -O python.tar.x… 55.8MB 16 | 4 days ago /bin/sh -c #(nop) ENV PYTHON_VERSION=3.9.4 0B 17 | 9 days ago /bin/sh -c #(nop) ENV GPG_KEY=E3FF2839C048B… 0B 18 | 9 days ago /bin/sh -c apt-get update && apt-get install… 18MB 19 | 9 days ago /bin/sh -c #(nop) ENV LANG=C.UTF-8 0B 20 | 9 days ago /bin/sh -c #(nop) ENV PATH=/usr/local/bin:/… 0B 21 | 9 days ago /bin/sh -c set -ex; apt-get update; apt-ge… 510MB 22 | 9 days ago /bin/sh -c apt-get update && apt-get install… 146MB 23 | 9 days ago /bin/sh -c set -ex; if ! command -v gpg > /… 17.5MB 24 | 9 days ago /bin/sh -c set -eux; apt-get update; apt-g… 16.5MB 25 | 9 days ago /bin/sh -c #(nop) CMD ["bash"] 0B 26 | 9 days ago /bin/sh -c #(nop) ADD file:c254898ceb4172f05… 114MB 27 | -------------------------------------------------------------------------------- /Lesson-Files/01-Docker-Basics/02-Dockerfile-Optimize/dev1/dev3: -------------------------------------------------------------------------------- 1 | IMAGE CREATED CREATED BY SIZE COMMENT 2 | d22a2fea9825 13 seconds ago /bin/sh -c #(nop) CMD ["app.py" "--host" "0… 0B 3 | dd28e83fefef 13 seconds ago /bin/sh -c #(nop) ENTRYPOINT ["python"] 0B 4 | 3985df8dbc7d 13 seconds ago /bin/sh -c #(nop) EXPOSE 5000 0B 5 | 4a74fcc9db28 14 seconds ago /bin/sh -c #(nop) COPY dir:717deea22fa9dbd3e… 397B 6 | e588841665b4 14 seconds ago /bin/sh -c pip install -r requirements.txt 11.1MB 7 | 6fbe9e569349 19 seconds ago /bin/sh -c #(nop) WORKDIR /app 0B 8 | fbbf16cf0241 19 seconds ago /bin/sh -c #(nop) COPY file:430e8697ad5d9784… 14B 9 | c5dc8db7de7e 6 days ago /bin/sh -c #(nop) CMD ["python3"] 0B 10 | 6 days ago /bin/sh -c set -ex; wget -O get-pip.py "$P… 8.01MB 11 | 6 days ago /bin/sh -c #(nop) ENV PYTHON_GET_PIP_SHA256… 0B 12 | 6 days ago /bin/sh -c #(nop) ENV PYTHON_GET_PIP_URL=ht… 0B 13 | 6 days ago /bin/sh -c #(nop) ENV PYTHON_PIP_VERSION=21… 0B 14 | 6 days ago /bin/sh -c cd /usr/local/bin && ln -s idle3… 32B 15 | 6 days ago /bin/sh -c set -ex && wget -O python.tar.x… 53.5MB 16 | 6 days ago /bin/sh -c #(nop) ENV PYTHON_VERSION=3.8.9 0B 17 | 9 days ago /bin/sh -c #(nop) ENV GPG_KEY=E3FF2839C048B… 0B 18 | 9 days ago /bin/sh -c apt-get update && apt-get install… 18MB 19 | 9 days ago /bin/sh -c #(nop) ENV LANG=C.UTF-8 0B 20 | 9 days ago /bin/sh -c #(nop) ENV PATH=/usr/local/bin:/… 0B 21 | 9 days ago /bin/sh -c set -ex; apt-get update; apt-ge… 510MB 22 | 9 days ago /bin/sh -c apt-get update && apt-get install… 146MB 23 | 9 days ago /bin/sh -c set -ex; if ! command -v gpg > /… 17.5MB 24 | 9 days ago /bin/sh -c set -eux; apt-get update; apt-g… 16.5MB 25 | 9 days ago /bin/sh -c #(nop) CMD ["bash"] 0B 26 | 9 days ago /bin/sh -c #(nop) ADD file:c254898ceb4172f05… 114MB 27 | -------------------------------------------------------------------------------- /Lesson-Files/01-Docker-Basics/02-Dockerfile-Optimize/dev1/dev4: -------------------------------------------------------------------------------- 1 | IMAGE CREATED CREATED BY SIZE COMMENT 2 | 9bde6f1dedd7 11 seconds ago /bin/sh -c #(nop) CMD ["app.py" "--host" "0… 0B 3 | 3d049dc26d17 11 seconds ago /bin/sh -c #(nop) ENTRYPOINT ["python"] 0B 4 | 27e8f99bf8fc 11 seconds ago /bin/sh -c #(nop) EXPOSE 5000 0B 5 | 37ea02e4880c 11 seconds ago /bin/sh -c #(nop) COPY dir:2f76f2b892c9fa5dc… 397B 6 | 45b8b595bac5 12 seconds ago /bin/sh -c pip install -r requirements.txt 11.1MB 7 | cc383be8692b 17 seconds ago /bin/sh -c #(nop) WORKDIR /app 0B 8 | 3f5f29c8a2cb 17 seconds ago /bin/sh -c #(nop) COPY file:430e8697ad5d9784… 14B 9 | c5dc8db7de7e 6 days ago /bin/sh -c #(nop) CMD ["python3"] 0B 10 | 6 days ago /bin/sh -c set -ex; wget -O get-pip.py "$P… 8.01MB 11 | 6 days ago /bin/sh -c #(nop) ENV PYTHON_GET_PIP_SHA256… 0B 12 | 6 days ago /bin/sh -c #(nop) ENV PYTHON_GET_PIP_URL=ht… 0B 13 | 6 days ago /bin/sh -c #(nop) ENV PYTHON_PIP_VERSION=21… 0B 14 | 6 days ago /bin/sh -c cd /usr/local/bin && ln -s idle3… 32B 15 | 6 days ago /bin/sh -c set -ex && wget -O python.tar.x… 53.5MB 16 | 6 days ago /bin/sh -c #(nop) ENV PYTHON_VERSION=3.8.9 0B 17 | 9 days ago /bin/sh -c #(nop) ENV GPG_KEY=E3FF2839C048B… 0B 18 | 9 days ago /bin/sh -c apt-get update && apt-get install… 18MB 19 | 9 days ago /bin/sh -c #(nop) ENV LANG=C.UTF-8 0B 20 | 9 days ago /bin/sh -c #(nop) ENV PATH=/usr/local/bin:/… 0B 21 | 9 days ago /bin/sh -c set -ex; apt-get update; apt-ge… 510MB 22 | 9 days ago /bin/sh -c apt-get update && apt-get install… 146MB 23 | 9 days ago /bin/sh -c set -ex; if ! command -v gpg > /… 17.5MB 24 | 9 days ago /bin/sh -c set -eux; apt-get update; apt-g… 16.5MB 25 | 9 days ago /bin/sh -c #(nop) CMD ["bash"] 0B 26 | 9 days ago /bin/sh -c #(nop) ADD file:c254898ceb4172f05… 114MB 27 | -------------------------------------------------------------------------------- /Lesson-Files/01-Docker-Basics/02-Dockerfile-Optimize/dev1/test.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morethancertified/mtc-docker/17973c01e67f803c05e91ad71a62a5214c552a8a/Lesson-Files/01-Docker-Basics/02-Dockerfile-Optimize/dev1/test.txt -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/01-Hello-Compose/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/01-Hello-Compose/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/01-Hello-Compose/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/01-Hello-Compose/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | container_name: dev 5 | build: ./dev1/ 6 | ports: 7 | - "5000:5000" 8 | volumes: 9 | - ./dev1/app/:/app/ -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/02-Named-Volume/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/02-Named-Volume/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/02-Named-Volume/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/02-Named-Volume/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | build: ./dev1/ 5 | ports: 6 | - "5000:5000" 7 | volumes: 8 | - type: volume 9 | source: dev1-vol 10 | target: /app 11 | volumes: 12 | dev1-vol: {} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/03-Node-Red/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/03-Node-Red/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/03-Node-Red/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/03-Node-Red/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | container_name: dev 5 | build: ./dev1/ 6 | ports: 7 | - "5000:5000" 8 | volumes: 9 | - type: volume 10 | source: dev1-vol 11 | target: /app 12 | nodered: 13 | container_name: nodered 14 | image: "nodered/node-red" 15 | ports: 16 | - "1880:1880" 17 | volumes: 18 | - nodered-vol:/data 19 | volumes: 20 | dev1-vol: {} 21 | nodered-vol: {} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/04-Node-Red-Config/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/04-Node-Red-Config/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/04-Node-Red-Config/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/04-Node-Red-Config/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | build: ./dev1/ 5 | ports: 6 | - "5000:5000" 7 | volumes: 8 | - type: volume 9 | source: dev1-vol 10 | target: /app 11 | nodered: 12 | build: ./node-red/ 13 | ports: 14 | - "1880:1880" 15 | volumes: 16 | - nodered-vol:/data 17 | volumes: 18 | dev1-vol: {} 19 | nodered-vol: {} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/04-Node-Red-Config/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | COPY ./flows.json /data/flows.json 4 | 5 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/04-Node-Red-Config/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [{"id":"f6f2187d.f17ca8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"e6078e0e.d41fa","type":"inject","z":"f6f2187d.f17ca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":450,"y":340,"wires":[["d1dff1b8.d4bd3"]]},{"id":"d1dff1b8.d4bd3","type":"http request","z":"f6f2187d.f17ca8","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://api:5000","tls":"","persist":false,"proxy":"","authType":"","x":680,"y":340,"wires":[["a82b5782.bd03d8"]]},{"id":"a82b5782.bd03d8","type":"debug","z":"f6f2187d.f17ca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":920,"y":340,"wires":[]}] -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/05-Node-Red-Config-Part-2/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/05-Node-Red-Config-Part-2/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/05-Node-Red-Config-Part-2/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/05-Node-Red-Config-Part-2/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | build: ./dev1/ 5 | ports: 6 | - "5000:5000" 7 | volumes: 8 | - type: volume 9 | source: dev1-vol 10 | target: /app 11 | nodered: 12 | build: 13 | context: ./node-red/ 14 | environment: 15 | - API_URL=api:5000 16 | ports: 17 | - "1880:1880" 18 | volumes: 19 | - nodered-vol:/data 20 | volumes: 21 | dev1-vol: {} 22 | nodered-vol: {} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/05-Node-Red-Config-Part-2/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | COPY ./flows.json /data/flows.json 4 | 5 | #WORKDIR /data 6 | 7 | ENV API_URL="172.21.0.2" 8 | 9 | #RUN sed -i "s/API_IP:API_PORT/${API_IP}:${API_PORT}/g" /data/flows.json 10 | 11 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/05-Node-Red-Config-Part-2/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "f6f2187d.f17ca8", 4 | "type": "tab", 5 | "label": "Flow 1", 6 | "disabled": false, 7 | "info": "" 8 | }, 9 | { 10 | "id": "9d41cfd6.5fe44", 11 | "type": "inject", 12 | "z": "f6f2187d.f17ca8", 13 | "name": "", 14 | "props": [ 15 | { 16 | "p": "payload" 17 | }, 18 | { 19 | "p": "topic", 20 | "vt": "str" 21 | } 22 | ], 23 | "repeat": "", 24 | "crontab": "", 25 | "once": false, 26 | "onceDelay": 0.1, 27 | "topic": "", 28 | "payload": "", 29 | "payloadType": "date", 30 | "x": 310, 31 | "y": 400, 32 | "wires": [ 33 | [ 34 | "10d047b2.ab2c38" 35 | ] 36 | ] 37 | }, 38 | { 39 | "id": "10d047b2.ab2c38", 40 | "type": "http request", 41 | "z": "f6f2187d.f17ca8", 42 | "name": "", 43 | "method": "GET", 44 | "ret": "txt", 45 | "paytoqs": "ignore", 46 | "url": "${API_URL}", 47 | "tls": "", 48 | "persist": false, 49 | "proxy": "", 50 | "authType": "", 51 | "x": 560, 52 | "y": 400, 53 | "wires": [ 54 | [ 55 | "4c7a1fb7.c1aa9" 56 | ] 57 | ] 58 | }, 59 | { 60 | "id": "4c7a1fb7.c1aa9", 61 | "type": "debug", 62 | "z": "f6f2187d.f17ca8", 63 | "name": "", 64 | "active": true, 65 | "tosidebar": true, 66 | "console": false, 67 | "tostatus": false, 68 | "complete": "false", 69 | "statusVal": "", 70 | "statusType": "auto", 71 | "x": 810, 72 | "y": 400, 73 | "wires": [] 74 | } 75 | ] -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/06-InfluxDB/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/06-InfluxDB/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/06-InfluxDB/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/06-InfluxDB/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | container_name: dev1 5 | build: ./dev1/ 6 | ports: 7 | - "5000:5000" 8 | volumes: 9 | - type: volume 10 | source: dev1-vol 11 | target: /app 12 | nodered: 13 | container_name: nodered 14 | build: ./nodered/ 15 | ports: 16 | - "1880:1880" 17 | volumes: 18 | - type: volume 19 | source: nodered-vol 20 | target: /data 21 | influxdb: 22 | container_name: influxdb 23 | image: influxdb 24 | ports: 25 | - "8086:8086" 26 | volumes: 27 | - type: volume 28 | source: influxdb-vol 29 | target: /var/lib/influxdb2 30 | volumes: 31 | dev1-vol: {} 32 | nodered-vol: {} 33 | influxdb-vol: {} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/06-InfluxDB/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | COPY ./flows.json /data/flows.json 4 | 5 | #WORKDIR /data 6 | 7 | ENV API_URL="172.21.0.2" 8 | 9 | #RUN sed -i "s/API_IP:API_PORT/${API_IP}:${API_PORT}/g" /data/flows.json 10 | 11 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/06-InfluxDB/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "f6f2187d.f17ca8", 4 | "type": "tab", 5 | "label": "Flow 1", 6 | "disabled": false, 7 | "info": "" 8 | }, 9 | { 10 | "id": "9d41cfd6.5fe44", 11 | "type": "inject", 12 | "z": "f6f2187d.f17ca8", 13 | "name": "", 14 | "props": [ 15 | { 16 | "p": "payload" 17 | }, 18 | { 19 | "p": "topic", 20 | "vt": "str" 21 | } 22 | ], 23 | "repeat": "", 24 | "crontab": "", 25 | "once": false, 26 | "onceDelay": 0.1, 27 | "topic": "", 28 | "payload": "", 29 | "payloadType": "date", 30 | "x": 310, 31 | "y": 400, 32 | "wires": [ 33 | [ 34 | "10d047b2.ab2c38" 35 | ] 36 | ] 37 | }, 38 | { 39 | "id": "10d047b2.ab2c38", 40 | "type": "http request", 41 | "z": "f6f2187d.f17ca8", 42 | "name": "", 43 | "method": "GET", 44 | "ret": "txt", 45 | "paytoqs": "ignore", 46 | "url": "${API_URL}", 47 | "tls": "", 48 | "persist": false, 49 | "proxy": "", 50 | "authType": "", 51 | "x": 560, 52 | "y": 400, 53 | "wires": [ 54 | [ 55 | "4c7a1fb7.c1aa9" 56 | ] 57 | ] 58 | }, 59 | { 60 | "id": "4c7a1fb7.c1aa9", 61 | "type": "debug", 62 | "z": "f6f2187d.f17ca8", 63 | "name": "", 64 | "active": true, 65 | "tosidebar": true, 66 | "console": false, 67 | "tostatus": false, 68 | "complete": "false", 69 | "statusVal": "", 70 | "statusType": "auto", 71 | "x": 810, 72 | "y": 400, 73 | "wires": [] 74 | } 75 | ] -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/07-InfluxDB-config/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/07-InfluxDB-config/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/07-InfluxDB-config/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/07-InfluxDB-config/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | container_name: dev1 5 | build: ./dev1/ 6 | ports: 7 | - "5000:5000" 8 | volumes: 9 | - type: volume 10 | source: dev1-vol 11 | target: /app 12 | nodered: 13 | container_name: nodered 14 | build: ./nodered/ 15 | ports: 16 | - "1880:1880" 17 | volumes: 18 | - type: volume 19 | source: nodered-vol 20 | target: /data 21 | influxdb: 22 | container_name: influxdb 23 | image: influxdb 24 | ports: 25 | - "8086:8086" 26 | volumes: 27 | - type: volume 28 | source: influxdb-vol 29 | target: /var/lib/influxdb2 30 | environment: 31 | - DOCKER_INFLUXDB_INIT_MODE=setup 32 | - DOCKER_INFLUXDB_INIT_USERNAME=mtcderek 33 | - DOCKER_INFLUXDB_INIT_PASSWORD=mtcdere 34 | - DOCKER_INFLUXDB_INIT_ORG=mtc 35 | - DOCKER_INFLUXDB_INIT_BUCKET=mtcbucket 36 | volumes: 37 | dev1-vol: {} 38 | nodered-vol: {} 39 | influxdb-vol: {} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/07-InfluxDB-config/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | COPY ./flows.json /data/flows.json 4 | 5 | #WORKDIR /data 6 | 7 | ENV API_URL="172.21.0.2" 8 | 9 | #RUN sed -i "s/API_IP:API_PORT/${API_IP}:${API_PORT}/g" /data/flows.json 10 | 11 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/07-InfluxDB-config/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "f6f2187d.f17ca8", 4 | "type": "tab", 5 | "label": "Flow 1", 6 | "disabled": false, 7 | "info": "" 8 | }, 9 | { 10 | "id": "9d41cfd6.5fe44", 11 | "type": "inject", 12 | "z": "f6f2187d.f17ca8", 13 | "name": "", 14 | "props": [ 15 | { 16 | "p": "payload" 17 | }, 18 | { 19 | "p": "topic", 20 | "vt": "str" 21 | } 22 | ], 23 | "repeat": "", 24 | "crontab": "", 25 | "once": false, 26 | "onceDelay": 0.1, 27 | "topic": "", 28 | "payload": "", 29 | "payloadType": "date", 30 | "x": 310, 31 | "y": 400, 32 | "wires": [ 33 | [ 34 | "10d047b2.ab2c38" 35 | ] 36 | ] 37 | }, 38 | { 39 | "id": "10d047b2.ab2c38", 40 | "type": "http request", 41 | "z": "f6f2187d.f17ca8", 42 | "name": "", 43 | "method": "GET", 44 | "ret": "txt", 45 | "paytoqs": "ignore", 46 | "url": "${API_URL}", 47 | "tls": "", 48 | "persist": false, 49 | "proxy": "", 50 | "authType": "", 51 | "x": 560, 52 | "y": 400, 53 | "wires": [ 54 | [ 55 | "4c7a1fb7.c1aa9" 56 | ] 57 | ] 58 | }, 59 | { 60 | "id": "4c7a1fb7.c1aa9", 61 | "type": "debug", 62 | "z": "f6f2187d.f17ca8", 63 | "name": "", 64 | "active": true, 65 | "tosidebar": true, 66 | "console": false, 67 | "tostatus": false, 68 | "complete": "false", 69 | "statusVal": "", 70 | "statusType": "auto", 71 | "x": 810, 72 | "y": 400, 73 | "wires": [] 74 | } 75 | ] -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/08-InfluxDB-Healthcheck/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/08-InfluxDB-Healthcheck/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/08-InfluxDB-Healthcheck/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/08-InfluxDB-Healthcheck/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | container_name: dev1 5 | build: ./dev1/ 6 | ports: 7 | - "5000:5000" 8 | volumes: 9 | - type: volume 10 | source: dev1-vol 11 | target: /app 12 | nodered: 13 | container_name: nodered 14 | build: ./nodered/ 15 | ports: 16 | - "1880:1880" 17 | volumes: 18 | - type: volume 19 | source: nodered-vol 20 | target: /data 21 | influxdb: 22 | container_name: influxdb 23 | build: ./influxdb/ 24 | ports: 25 | - "8086:8086" 26 | volumes: 27 | - type: volume 28 | source: influxdb-vol 29 | target: /var/lib/influxdb2 30 | environment: 31 | - DOCKER_INFLUXDB_INIT_MODE=setup 32 | - DOCKER_INFLUXDB_INIT_USERNAME=mtcderek 33 | - DOCKER_INFLUXDB_INIT_PASSWORD=mtcderek 34 | - DOCKER_INFLUXDB_INIT_ORG=mtc 35 | - DOCKER_INFLUXDB_INIT_BUCKET=mtcbucket 36 | volumes: 37 | dev1-vol: {} 38 | nodered-vol: {} 39 | influxdb-vol: {} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/08-InfluxDB-Healthcheck/influxdb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM influxdb 2 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:8086 || nc -zv localhost 8086 || exit 1 -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/08-InfluxDB-Healthcheck/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | COPY ./flows.json /data/flows.json 4 | 5 | #WORKDIR /data 6 | 7 | ENV API_URL="172.21.0.2" 8 | 9 | #RUN sed -i "s/API_IP:API_PORT/${API_IP}:${API_PORT}/g" /data/flows.json 10 | 11 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/08-InfluxDB-Healthcheck/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "f6f2187d.f17ca8", 4 | "type": "tab", 5 | "label": "Flow 1", 6 | "disabled": false, 7 | "info": "" 8 | }, 9 | { 10 | "id": "9d41cfd6.5fe44", 11 | "type": "inject", 12 | "z": "f6f2187d.f17ca8", 13 | "name": "", 14 | "props": [ 15 | { 16 | "p": "payload" 17 | }, 18 | { 19 | "p": "topic", 20 | "vt": "str" 21 | } 22 | ], 23 | "repeat": "", 24 | "crontab": "", 25 | "once": false, 26 | "onceDelay": 0.1, 27 | "topic": "", 28 | "payload": "", 29 | "payloadType": "date", 30 | "x": 310, 31 | "y": 400, 32 | "wires": [ 33 | [ 34 | "10d047b2.ab2c38" 35 | ] 36 | ] 37 | }, 38 | { 39 | "id": "10d047b2.ab2c38", 40 | "type": "http request", 41 | "z": "f6f2187d.f17ca8", 42 | "name": "", 43 | "method": "GET", 44 | "ret": "txt", 45 | "paytoqs": "ignore", 46 | "url": "${API_URL}", 47 | "tls": "", 48 | "persist": false, 49 | "proxy": "", 50 | "authType": "", 51 | "x": 560, 52 | "y": 400, 53 | "wires": [ 54 | [ 55 | "4c7a1fb7.c1aa9" 56 | ] 57 | ] 58 | }, 59 | { 60 | "id": "4c7a1fb7.c1aa9", 61 | "type": "debug", 62 | "z": "f6f2187d.f17ca8", 63 | "name": "", 64 | "active": true, 65 | "tosidebar": true, 66 | "console": false, 67 | "tostatus": false, 68 | "complete": "false", 69 | "statusVal": "", 70 | "statusType": "auto", 71 | "x": 810, 72 | "y": 400, 73 | "wires": [] 74 | } 75 | ] -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/09-Influxdb-nodered-automation/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/09-Influxdb-nodered-automation/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/09-Influxdb-nodered-automation/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/09-Influxdb-nodered-automation/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | container_name: dev1 5 | build: ./dev1/ 6 | ports: 7 | - "5000:5000" 8 | volumes: 9 | - type: volume 10 | source: dev1-vol 11 | target: /app 12 | nodered: 13 | container_name: nodered 14 | build: ./nodered/ 15 | ports: 16 | - "1880:1880" 17 | volumes: 18 | - type: volume 19 | source: nodered-vol 20 | target: /data 21 | influxdb: 22 | container_name: influxdb 23 | build: ./influxdb/ 24 | ports: 25 | - "8086:8086" 26 | volumes: 27 | - type: volume 28 | source: influxdb-vol 29 | target: /var/lib/influxdb2 30 | environment: 31 | - DOCKER_INFLUXDB_INIT_MODE=setup 32 | - DOCKER_INFLUXDB_INIT_USERNAME=mtcderek 33 | - DOCKER_INFLUXDB_INIT_PASSWORD=mtcderek 34 | - DOCKER_INFLUXDB_INIT_ORG=mtc 35 | - DOCKER_INFLUXDB_INIT_BUCKET=mtcbucket 36 | - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=mtcderektoken 37 | volumes: 38 | dev1-vol: {} 39 | nodered-vol: {} 40 | influxdb-vol: {} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/09-Influxdb-nodered-automation/influxdb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM influxdb 2 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:8086 || nc -zv localhost 8086 || exit 1 -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/09-Influxdb-nodered-automation/nodered.1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | RUN npm install node-red-contrib-influxdb 4 | 5 | COPY ./settings.js /data/settings.js 6 | COPY ./flows_cred.json /data/flows_cred.json 7 | COPY ./flows.json /data/flows.json 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/09-Influxdb-nodered-automation/nodered.1/flows.json: -------------------------------------------------------------------------------- 1 | [{"id":"f6f2187d.f17ca8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"817ac0aa.0e86a","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"influxdb","usetls":false,"tls":"","influxdbVersion":"2.0","url":"http://influxdb:8086","rejectUnauthorized":true},{"id":"9d41cfd6.5fe44","type":"inject","z":"f6f2187d.f17ca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":250,"y":400,"wires":[["10d047b2.ab2c38"]]},{"id":"10d047b2.ab2c38","type":"http request","z":"f6f2187d.f17ca8","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://dev1:5000","tls":"","persist":false,"proxy":"","authType":"","x":490,"y":400,"wires":[["4c7a1fb7.c1aa9","8fb09797.28ba78"]]},{"id":"4c7a1fb7.c1aa9","type":"debug","z":"f6f2187d.f17ca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":870,"y":400,"wires":[]},{"id":"669e3330.0321bc","type":"influxdb out","z":"f6f2187d.f17ca8","influxdb":"817ac0aa.0e86a","name":"influxdb","measurement":"data","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"mtc","bucket":"mtcbucket","x":900,"y":520,"wires":[]},{"id":"8fb09797.28ba78","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n [{\n temp: msg.payload.data.temp,\n },\n {\n device: msg.payload.data.device,\n name: msg.payload.data.name\n }],\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":680,"y":520,"wires":[["4c7a1fb7.c1aa9","669e3330.0321bc"]]}] -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/09-Influxdb-nodered-automation/nodered.1/flows_cred.json: -------------------------------------------------------------------------------- 1 | {"$":"b81dbfba99b392b4e03073c50ba6986ftanl6PGFnT7H0JVw+/CZEm6P+R0TcS4KTYQYnmDOR7KPxu8xkYvIhbO8Ky4="} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/09-Influxdb-nodered-automation/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | RUN npm install node-red-contrib-influxdb 4 | 5 | COPY ./settings.js /data/settings.js 6 | COPY ./flows_cred.json /data/flows_cred.json 7 | COPY ./flows.json /data/flows.json 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/09-Influxdb-nodered-automation/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [{"id":"f6f2187d.f17ca8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"817ac0aa.0e86a","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"influxdb","usetls":false,"tls":"","influxdbVersion":"2.0","url":"http://influxdb:8086","rejectUnauthorized":true},{"id":"9d41cfd6.5fe44","type":"inject","z":"f6f2187d.f17ca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":250,"y":400,"wires":[["10d047b2.ab2c38"]]},{"id":"10d047b2.ab2c38","type":"http request","z":"f6f2187d.f17ca8","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://dev1:5000","tls":"","persist":false,"proxy":"","authType":"","x":490,"y":400,"wires":[["4c7a1fb7.c1aa9","8fb09797.28ba78"]]},{"id":"4c7a1fb7.c1aa9","type":"debug","z":"f6f2187d.f17ca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":870,"y":400,"wires":[]},{"id":"669e3330.0321bc","type":"influxdb out","z":"f6f2187d.f17ca8","influxdb":"817ac0aa.0e86a","name":"influxdb","measurement":"data","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"mtc","bucket":"mtcbucket","x":900,"y":520,"wires":[]},{"id":"8fb09797.28ba78","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n [{\n temp: msg.payload.data.temp,\n },\n {\n device: msg.payload.data.device,\n name: msg.payload.data.name\n }],\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":680,"y":520,"wires":[["4c7a1fb7.c1aa9","669e3330.0321bc"]]}] -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/09-Influxdb-nodered-automation/nodered/flows_cred.json: -------------------------------------------------------------------------------- 1 | {"817ac0aa.0e86a":{"token":"${INFLUXDB_TOKEN}"}} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/10-nodered-credentials/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/10-nodered-credentials/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/10-nodered-credentials/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/10-nodered-credentials/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | container_name: dev1 5 | build: ./dev1/ 6 | ports: 7 | - "5000:5000" 8 | volumes: 9 | - type: volume 10 | source: dev1-vol 11 | target: /app 12 | nodered: 13 | container_name: nodered 14 | build: ./nodered/ 15 | ports: 16 | - "1880:1880" 17 | volumes: 18 | - type: volume 19 | source: nodered-vol 20 | target: /data 21 | environment: 22 | - INFLUXDB_TOKEN=mtcderektoken 23 | influxdb: 24 | container_name: influxdb 25 | build: ./influxdb/ 26 | ports: 27 | - "8086:8086" 28 | volumes: 29 | - type: volume 30 | source: influxdb-vol 31 | target: /var/lib/influxdb2 32 | environment: 33 | - DOCKER_INFLUXDB_INIT_MODE=setup 34 | 35 | - DOCKER_INFLUXDB_INIT_USERNAME=mtcderek 36 | - DOCKER_INFLUXDB_INIT_PASSWORD=mtcderek 37 | - DOCKER_INFLUXDB_INIT_ORG=mtc 38 | - DOCKER_INFLUXDB_INIT_BUCKET=mtcbucket 39 | - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=mtcderektoken 40 | volumes: 41 | dev1-vol: {} 42 | nodered-vol: {} 43 | influxdb-vol: {} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/10-nodered-credentials/influxdb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM influxdb 2 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:8086 || nc -zv localhost 8086 || exit 1 -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/10-nodered-credentials/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | RUN npm install node-red-contrib-influxdb 4 | 5 | COPY ./settings.js /data/settings.js 6 | COPY ./flows_cred.json /data/flows_cred.json 7 | COPY ./flows.json /data/flows.json 8 | 9 | 10 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/10-nodered-credentials/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [{"id":"f6f2187d.f17ca8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"8c2bb514.1d2198","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"influxdb","usetls":false,"tls":"","influxdbVersion":"2.0","url":"http://influxdb:8086","rejectUnauthorized":true},{"id":"9d41cfd6.5fe44","type":"inject","z":"f6f2187d.f17ca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":320,"y":400,"wires":[["10d047b2.ab2c38"]]},{"id":"10d047b2.ab2c38","type":"http request","z":"f6f2187d.f17ca8","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://dev1:5000","tls":"","persist":false,"proxy":"","authType":"","x":560,"y":400,"wires":[["4c7a1fb7.c1aa9","220b7260.eab46e"]]},{"id":"4c7a1fb7.c1aa9","type":"debug","z":"f6f2187d.f17ca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":810,"y":400,"wires":[]},{"id":"a536e7c7.4cb5a8","type":"influxdb out","z":"f6f2187d.f17ca8","influxdb":"8c2bb514.1d2198","name":"influxdb","measurement":"data","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"mtc","bucket":"mtcbucket","x":800,"y":500,"wires":[]},{"id":"220b7260.eab46e","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n [{\n temp: msg.payload.data.temp,\n },\n {\n device: msg.payload.data.device,\n name: msg.payload.data.name\n }],\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":500,"wires":[["a536e7c7.4cb5a8","4c7a1fb7.c1aa9"]]}] -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/10-nodered-credentials/nodered/flows_cred.json: -------------------------------------------------------------------------------- 1 | {"8c2bb514.1d2198":{"token":"mtcderektoken"}} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/11-Grafana/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/11-Grafana/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/11-Grafana/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/11-Grafana/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | container_name: dev1 5 | build: ./dev1/ 6 | ports: 7 | - "5000:5000" 8 | volumes: 9 | - type: volume 10 | source: dev1-vol 11 | target: /app 12 | nodered: 13 | container_name: nodered 14 | build: ./nodered/ 15 | ports: 16 | - "1880:1880" 17 | volumes: 18 | - type: volume 19 | source: nodered-vol 20 | target: /data 21 | environment: 22 | - INFLUXDB_TOKEN=mtcderektoken 23 | influxdb: 24 | container_name: influxdb 25 | build: ./influxdb/ 26 | ports: 27 | - "8086:8086" 28 | volumes: 29 | - type: volume 30 | source: influxdb-vol 31 | target: /var/lib/influxdb2 32 | environment: 33 | - DOCKER_INFLUXDB_INIT_MODE=setup 34 | - DOCKER_INFLUXDB_INIT_USERNAME=mtcderek 35 | - DOCKER_INFLUXDB_INIT_PASSWORD=mtcderek 36 | - DOCKER_INFLUXDB_INIT_ORG=mtc 37 | - DOCKER_INFLUXDB_INIT_BUCKET=mtcbucket 38 | - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=mtcderektoken 39 | grafana: 40 | container_name: grafana 41 | image: grafana/grafana 42 | environment: 43 | - GF_SECURITY_ADMIN_USER=mtcderek 44 | - GF_SECURITY_ADMIN_PASSWORD=mtcderek 45 | ports: 46 | - "3000:3000" 47 | volumes: 48 | - type: volume 49 | source: grafana-vol 50 | target: /var/lib/grafana 51 | volumes: 52 | dev1-vol: {} 53 | nodered-vol: {} 54 | influxdb-vol: {} 55 | grafana-vol: {} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/11-Grafana/influxdb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM influxdb 2 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:8086 || nc -zv localhost 8086 || exit 1 -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/11-Grafana/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | RUN npm install node-red-contrib-influxdb 4 | 5 | COPY ./settings.js /data/settings.js 6 | COPY ./flows_cred.json /data/flows_cred.json 7 | COPY ./flows.json /data/flows.json 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/11-Grafana/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [{"id":"f6f2187d.f17ca8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"817ac0aa.0e86a","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"influxdb","usetls":false,"tls":"","influxdbVersion":"2.0","url":"http://influxdb:8086","rejectUnauthorized":true},{"id":"9d41cfd6.5fe44","type":"inject","z":"f6f2187d.f17ca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":250,"y":400,"wires":[["10d047b2.ab2c38"]]},{"id":"10d047b2.ab2c38","type":"http request","z":"f6f2187d.f17ca8","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://dev1:5000","tls":"","persist":false,"proxy":"","authType":"","x":490,"y":400,"wires":[["4c7a1fb7.c1aa9","8fb09797.28ba78"]]},{"id":"4c7a1fb7.c1aa9","type":"debug","z":"f6f2187d.f17ca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":870,"y":400,"wires":[]},{"id":"669e3330.0321bc","type":"influxdb out","z":"f6f2187d.f17ca8","influxdb":"817ac0aa.0e86a","name":"influxdb","measurement":"data","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"mtc","bucket":"mtcbucket","x":900,"y":520,"wires":[]},{"id":"8fb09797.28ba78","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n [{\n temp: msg.payload.data.temp,\n },\n {\n device: msg.payload.data.device,\n name: msg.payload.data.name\n }],\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":680,"y":520,"wires":[["4c7a1fb7.c1aa9","669e3330.0321bc"]]}] -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/11-Grafana/nodered/flows_cred.json: -------------------------------------------------------------------------------- 1 | {"817ac0aa.0e86a":{"token":"${INFLUXDB_TOKEN}"}} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/12-Grafana-Config/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/12-Grafana-Config/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/12-Grafana-Config/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/12-Grafana-Config/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | container_name: dev1 5 | build: ./dev1/ 6 | ports: 7 | - "5000:5000" 8 | volumes: 9 | - type: volume 10 | source: dev1-vol 11 | target: /app 12 | nodered: 13 | container_name: nodered 14 | build: ./nodered/ 15 | ports: 16 | - "1880:1880" 17 | volumes: 18 | - type: volume 19 | source: nodered-vol 20 | target: /data 21 | environment: 22 | - INFLUXDB_TOKEN=mtcderektoken 23 | influxdb: 24 | container_name: influxdb 25 | build: ./influxdb/ 26 | ports: 27 | - "8086:8086" 28 | volumes: 29 | - type: volume 30 | source: influxdb-vol 31 | target: /var/lib/influxdb2 32 | environment: 33 | - DOCKER_INFLUXDB_INIT_MODE=setup 34 | - DOCKER_INFLUXDB_INIT_USERNAME=mtcderek 35 | - DOCKER_INFLUXDB_INIT_PASSWORD=mtcderek 36 | - DOCKER_INFLUXDB_INIT_ORG=mtc 37 | - DOCKER_INFLUXDB_INIT_BUCKET=mtcbucket 38 | - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=mtcderektoken 39 | grafana: 40 | container_name: grafana 41 | image: grafana/grafana 42 | environment: 43 | - GF_SECURITY_ADMIN_USER=admin 44 | - GF_SECURITY_ADMIN_PASSWORD=adminpass 45 | ports: 46 | - "3000:3000" 47 | volumes: 48 | - type: volume 49 | source: grafana-vol 50 | target: /var/lib/grafana 51 | volumes: 52 | dev1-vol: {} 53 | nodered-vol: {} 54 | influxdb-vol: {} 55 | grafana-vol: {} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/12-Grafana-Config/influxdb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM influxdb 2 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:8086 || nc -zv localhost 8086 || exit 1 -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/12-Grafana-Config/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | RUN npm install node-red-contrib-influxdb 4 | 5 | COPY ./settings.js /data/settings.js 6 | COPY ./flows_cred.json /data/flows_cred.json 7 | COPY ./flows.json /data/flows.json 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/12-Grafana-Config/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [{"id":"f6f2187d.f17ca8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"817ac0aa.0e86a","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"influxdb","usetls":false,"tls":"","influxdbVersion":"2.0","url":"http://influxdb:8086","rejectUnauthorized":true},{"id":"9d41cfd6.5fe44","type":"inject","z":"f6f2187d.f17ca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":250,"y":400,"wires":[["10d047b2.ab2c38"]]},{"id":"10d047b2.ab2c38","type":"http request","z":"f6f2187d.f17ca8","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://dev1:5000","tls":"","persist":false,"proxy":"","authType":"","x":490,"y":400,"wires":[["4c7a1fb7.c1aa9","8fb09797.28ba78"]]},{"id":"4c7a1fb7.c1aa9","type":"debug","z":"f6f2187d.f17ca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":870,"y":400,"wires":[]},{"id":"669e3330.0321bc","type":"influxdb out","z":"f6f2187d.f17ca8","influxdb":"817ac0aa.0e86a","name":"influxdb","measurement":"data","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"mtc","bucket":"mtcbucket","x":900,"y":520,"wires":[]},{"id":"8fb09797.28ba78","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n [{\n temp: msg.payload.data.temp,\n },\n {\n device: msg.payload.data.device,\n name: msg.payload.data.name\n }],\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":680,"y":520,"wires":[["4c7a1fb7.c1aa9","669e3330.0321bc"]]}] -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/12-Grafana-Config/nodered/flows_cred.json: -------------------------------------------------------------------------------- 1 | {"$":"83aad144e402be08a630d2098113487byWrOyiFpuZGNJu4c44l2ux2pWw6zU32Ba2xg+F/Q3ha2zMMj2gLOo3vBnsc="} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/13-Grafana-Automation/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/13-Grafana-Automation/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/13-Grafana-Automation/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/13-Grafana-Automation/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | container_name: dev1 5 | build: ./dev1/ 6 | ports: 7 | - "5000:5000" 8 | volumes: 9 | - type: volume 10 | source: dev1-vol 11 | target: /app 12 | nodered: 13 | container_name: nodered 14 | build: ./nodered/ 15 | ports: 16 | - "1880:1880" 17 | volumes: 18 | - type: volume 19 | source: nodered-vol 20 | target: /data 21 | environment: 22 | - INFLUXDB_TOKEN=mtcderektoken 23 | influxdb: 24 | container_name: influxdb 25 | build: ./influxdb/ 26 | ports: 27 | - "8086:8086" 28 | volumes: 29 | - type: volume 30 | source: influxdb-vol 31 | target: /var/lib/influxdb2 32 | environment: 33 | - DOCKER_INFLUXDB_INIT_MODE=setup 34 | - DOCKER_INFLUXDB_INIT_USERNAME=mtcderek 35 | - DOCKER_INFLUXDB_INIT_PASSWORD=mtcderek 36 | - DOCKER_INFLUXDB_INIT_ORG=mtc 37 | - DOCKER_INFLUXDB_INIT_BUCKET=mtcbucket 38 | - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=mtcderektoken 39 | grafana: 40 | container_name: grafana 41 | build: ./grafana/ 42 | image: grafana/grafana 43 | environment: 44 | - GF_SECURITY_ADMIN_USER=mtcderek 45 | - GF_SECURITY_ADMIN_PASSWORD=mtcderek 46 | - INFLUXDB_TOKEN=mtcderektoken 47 | ports: 48 | - "3000:3000" 49 | volumes: 50 | - type: volume 51 | source: grafana-vol 52 | target: /var/lib/grafana 53 | volumes: 54 | dev1-vol: {} 55 | nodered-vol: {} 56 | influxdb-vol: {} 57 | grafana-vol: {} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/13-Grafana-Automation/grafana/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM grafana/grafana 2 | COPY datasource.yml /etc/grafana/provisioning/datasources 3 | COPY dashboards/ /etc/grafana/provisioning/dashboards 4 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/13-Grafana-Automation/grafana/dashboards/dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | providers: 3 | - name: 'Temperature' 4 | orgId: 1 5 | folder: 'new dashboards' 6 | type: file 7 | disableDeletion: false 8 | allowUiUpdates: false 9 | options: 10 | path: /etc/grafana/provisioning/dashboards 11 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/13-Grafana-Automation/grafana/datasource.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | datasources: 4 | - name: influxdb 5 | type: influxdb 6 | access: proxy 7 | url: http://influxdb:8086 8 | editable: true 9 | secureJsonData: 10 | token: $INFLUXDB_TOKEN 11 | jsonData: 12 | version: Flux 13 | organization: mtc 14 | defaultBucket: mtcbucket -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/13-Grafana-Automation/influxdb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM influxdb 2 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:8086 || nc -zv localhost 8086 || exit 1 -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/13-Grafana-Automation/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | RUN npm install node-red-contrib-influxdb 4 | 5 | COPY ./settings.js /data/settings.js 6 | COPY ./flows_cred.json /data/flows_cred.json 7 | COPY ./flows.json /data/flows.json 8 | 9 | 10 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/13-Grafana-Automation/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [{"id":"f6f2187d.f17ca8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"8c2bb514.1d2198","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"influxdb","usetls":false,"tls":"","influxdbVersion":"2.0","url":"http://influxdb:8086","rejectUnauthorized":true},{"id":"9d41cfd6.5fe44","type":"inject","z":"f6f2187d.f17ca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":320,"y":400,"wires":[["10d047b2.ab2c38"]]},{"id":"10d047b2.ab2c38","type":"http request","z":"f6f2187d.f17ca8","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://dev1:5000","tls":"","persist":false,"proxy":"","authType":"","x":560,"y":400,"wires":[["4c7a1fb7.c1aa9","220b7260.eab46e"]]},{"id":"4c7a1fb7.c1aa9","type":"debug","z":"f6f2187d.f17ca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":810,"y":400,"wires":[]},{"id":"a536e7c7.4cb5a8","type":"influxdb out","z":"f6f2187d.f17ca8","influxdb":"8c2bb514.1d2198","name":"influxdb","measurement":"data","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"mtc","bucket":"mtcbucket","x":800,"y":500,"wires":[]},{"id":"220b7260.eab46e","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n [{\n temp: msg.payload.data.temp,\n },\n {\n device: msg.payload.data.device,\n name: msg.payload.data.name\n }],\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":500,"wires":[["a536e7c7.4cb5a8","4c7a1fb7.c1aa9"]]}] -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/13-Grafana-Automation/nodered/flows_cred.json: -------------------------------------------------------------------------------- 1 | {"8c2bb514.1d2198":{"token":"mtcderektoken"}} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/14-Postgres/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/14-Postgres/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/14-Postgres/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/14-Postgres/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | container_name: dev1 5 | build: ./dev1/ 6 | ports: 7 | - "5000:5000" 8 | volumes: 9 | - type: volume 10 | source: dev1-vol 11 | target: /app 12 | nodered: 13 | container_name: nodered 14 | build: ./nodered/ 15 | ports: 16 | - "1880:1880" 17 | volumes: 18 | - type: volume 19 | source: nodered-vol 20 | target: /data 21 | environment: 22 | - INFLUXDB_TOKEN=mtcderektoken 23 | influxdb: 24 | container_name: influxdb 25 | build: ./influxdb/ 26 | ports: 27 | - "8086:8086" 28 | volumes: 29 | - type: volume 30 | source: influxdb-vol 31 | target: /var/lib/influxdb2 32 | environment: 33 | - DOCKER_INFLUXDB_INIT_MODE=setup 34 | - DOCKER_INFLUXDB_INIT_USERNAME=mtcderek 35 | - DOCKER_INFLUXDB_INIT_PASSWORD=mtcderek 36 | - DOCKER_INFLUXDB_INIT_ORG=mtc 37 | - DOCKER_INFLUXDB_INIT_BUCKET=mtcbucket 38 | - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=mtcderektoken 39 | grafana: 40 | container_name: grafana 41 | build: ./grafana/ 42 | environment: 43 | - GF_SECURITY_ADMIN_USER=mtcderek 44 | - GF_SECURITY_ADMIN_PASSWORD=mtcderek 45 | - INFLUXDB_TOKEN=mtcderektoken 46 | ports: 47 | - "3000:3000" 48 | volumes: 49 | - type: volume 50 | source: grafana-vol 51 | target: /var/lib/grafana 52 | postgres: 53 | container_name: postgres 54 | build: ./postgres/ 55 | ports: 56 | - "5432:5432" 57 | volumes: 58 | - type: volume 59 | source: postgres-vol 60 | target: /var/lib/postgresql/data/ 61 | environment: 62 | - POSTGRES_USER=mtcderek 63 | - POSTGRES_PASSWORD=mtcderek 64 | - POSTGRES_DB=mtcdb 65 | volumes: 66 | dev1-vol: {} 67 | nodered-vol: {} 68 | influxdb-vol: {} 69 | grafana-vol: {} 70 | postgres-vol: {} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/14-Postgres/grafana/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM grafana/grafana 2 | COPY datasource.yml /etc/grafana/provisioning/datasources 3 | COPY dashboards/ /etc/grafana/provisioning/dashboards 4 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/14-Postgres/grafana/dashboards/dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | providers: 3 | - name: 'Temperature' 4 | orgId: 1 5 | folder: 'new dashboards' 6 | type: file 7 | disableDeletion: false 8 | allowUiUpdates: false 9 | options: 10 | path: /etc/grafana/provisioning/dashboards 11 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/14-Postgres/grafana/datasource.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | datasources: 4 | - name: influxdb 5 | type: influxdb 6 | access: proxy 7 | url: http://influxdb:8086 8 | editable: true 9 | secureJsonData: 10 | token: $INFLUXDB_TOKEN 11 | jsonData: 12 | version: Flux 13 | organization: mtc 14 | defaultBucket: mtcbucket -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/14-Postgres/influxdb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM influxdb 2 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:8086 || nc -zv localhost 8086 || exit 1 -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/14-Postgres/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | RUN npm install node-red-contrib-influxdb 4 | 5 | COPY ./settings.js /data/settings.js 6 | COPY ./flows_cred.json /data/flows_cred.json 7 | COPY ./flows.json /data/flows.json 8 | 9 | 10 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/14-Postgres/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [{"id":"f6f2187d.f17ca8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"8c2bb514.1d2198","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"influxdb","usetls":false,"tls":"","influxdbVersion":"2.0","url":"http://influxdb:8086","rejectUnauthorized":true},{"id":"9d41cfd6.5fe44","type":"inject","z":"f6f2187d.f17ca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":320,"y":400,"wires":[["10d047b2.ab2c38"]]},{"id":"10d047b2.ab2c38","type":"http request","z":"f6f2187d.f17ca8","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://dev1:5000","tls":"","persist":false,"proxy":"","authType":"","x":560,"y":400,"wires":[["4c7a1fb7.c1aa9","220b7260.eab46e"]]},{"id":"4c7a1fb7.c1aa9","type":"debug","z":"f6f2187d.f17ca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":810,"y":400,"wires":[]},{"id":"a536e7c7.4cb5a8","type":"influxdb out","z":"f6f2187d.f17ca8","influxdb":"8c2bb514.1d2198","name":"influxdb","measurement":"data","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"mtc","bucket":"mtcbucket","x":800,"y":500,"wires":[]},{"id":"220b7260.eab46e","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n [{\n temp: msg.payload.data.temp,\n },\n {\n device: msg.payload.data.device,\n name: msg.payload.data.name\n }],\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":500,"wires":[["a536e7c7.4cb5a8","4c7a1fb7.c1aa9"]]}] -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/14-Postgres/nodered/flows_cred.json: -------------------------------------------------------------------------------- 1 | {"8c2bb514.1d2198":{"token":"mtcderektoken"}} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/14-Postgres/postgres/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM postgres:13 -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/15-Postgres-Schema/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/15-Postgres-Schema/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/15-Postgres-Schema/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/15-Postgres-Schema/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | container_name: dev1 5 | build: ./dev1/ 6 | ports: 7 | - "5000:5000" 8 | volumes: 9 | - type: volume 10 | source: dev1-vol 11 | target: /app 12 | nodered: 13 | container_name: nodered 14 | build: ./nodered/ 15 | ports: 16 | - "1880:1880" 17 | volumes: 18 | - type: volume 19 | source: nodered-vol 20 | target: /data 21 | environment: 22 | - INFLUXDB_TOKEN=mtcderektoken 23 | influxdb: 24 | container_name: influxdb 25 | build: ./influxdb/ 26 | ports: 27 | - "8086:8086" 28 | volumes: 29 | - type: volume 30 | source: influxdb-vol 31 | target: /var/lib/influxdb2 32 | environment: 33 | - DOCKER_INFLUXDB_INIT_MODE=setup 34 | - DOCKER_INFLUXDB_INIT_USERNAME=mtcderek 35 | - DOCKER_INFLUXDB_INIT_PASSWORD=mtcderek 36 | - DOCKER_INFLUXDB_INIT_ORG=mtc 37 | - DOCKER_INFLUXDB_INIT_BUCKET=mtcbucket 38 | - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=mtcderektoken 39 | grafana: 40 | container_name: grafana 41 | build: ./grafana/ 42 | environment: 43 | - GF_SECURITY_ADMIN_USER=mtcderek 44 | - GF_SECURITY_ADMIN_PASSWORD=mtcderek 45 | - INFLUXDB_TOKEN=mtcderektoken 46 | ports: 47 | - "3000:3000" 48 | volumes: 49 | - type: volume 50 | source: grafana-vol 51 | target: /var/lib/grafana 52 | postgres: 53 | container_name: postgres 54 | build: ./postgres/ 55 | ports: 56 | - "5432:5432" 57 | volumes: 58 | - type: volume 59 | source: postgres-vol 60 | target: /var/lib/postgresql/data/ 61 | environment: 62 | - POSTGRES_USER=mtcderek 63 | - POSTGRES_PASSWORD=mtcderek 64 | - POSTGRES_DB=mtcdb 65 | volumes: 66 | dev1-vol: {} 67 | nodered-vol: {} 68 | influxdb-vol: {} 69 | grafana-vol: {} 70 | postgres-vol: {} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/15-Postgres-Schema/grafana/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM grafana/grafana 2 | COPY datasource.yml /etc/grafana/provisioning/datasources 3 | COPY dashboards/ /etc/grafana/provisioning/dashboards 4 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/15-Postgres-Schema/grafana/dashboards/dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | providers: 3 | - name: 'Temperature' 4 | orgId: 1 5 | folder: 'new dashboards' 6 | type: file 7 | disableDeletion: false 8 | allowUiUpdates: false 9 | options: 10 | path: /etc/grafana/provisioning/dashboards 11 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/15-Postgres-Schema/grafana/datasource.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | datasources: 4 | - name: influxdb 5 | type: influxdb 6 | access: proxy 7 | url: http://influxdb:8086 8 | editable: true 9 | secureJsonData: 10 | token: $INFLUXDB_TOKEN 11 | jsonData: 12 | version: Flux 13 | organization: mtc 14 | defaultBucket: mtcbucket -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/15-Postgres-Schema/influxdb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM influxdb 2 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:8086 || nc -zv localhost 8086 || exit 1 -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/15-Postgres-Schema/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | RUN npm install node-red-contrib-influxdb 4 | 5 | COPY ./settings.js /data/settings.js 6 | COPY ./flows_cred.json /data/flows_cred.json 7 | COPY ./flows.json /data/flows.json 8 | 9 | 10 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/15-Postgres-Schema/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [{"id":"f6f2187d.f17ca8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"8c2bb514.1d2198","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"influxdb","usetls":false,"tls":"","influxdbVersion":"2.0","url":"http://influxdb:8086","rejectUnauthorized":true},{"id":"9d41cfd6.5fe44","type":"inject","z":"f6f2187d.f17ca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":320,"y":400,"wires":[["10d047b2.ab2c38"]]},{"id":"10d047b2.ab2c38","type":"http request","z":"f6f2187d.f17ca8","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://dev1:5000","tls":"","persist":false,"proxy":"","authType":"","x":560,"y":400,"wires":[["4c7a1fb7.c1aa9","220b7260.eab46e"]]},{"id":"4c7a1fb7.c1aa9","type":"debug","z":"f6f2187d.f17ca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":810,"y":400,"wires":[]},{"id":"a536e7c7.4cb5a8","type":"influxdb out","z":"f6f2187d.f17ca8","influxdb":"8c2bb514.1d2198","name":"influxdb","measurement":"data","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"mtc","bucket":"mtcbucket","x":800,"y":500,"wires":[]},{"id":"220b7260.eab46e","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n [{\n temp: msg.payload.data.temp,\n },\n {\n device: msg.payload.data.device,\n name: msg.payload.data.name\n }],\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":500,"wires":[["a536e7c7.4cb5a8","4c7a1fb7.c1aa9"]]}] -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/15-Postgres-Schema/nodered/flows_cred.json: -------------------------------------------------------------------------------- 1 | {"8c2bb514.1d2198":{"token":"mtcderektoken"}} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/15-Postgres-Schema/postgres/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM postgres:13 2 | 3 | COPY schema.sql /docker-entrypoint-initdb.d/ -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/15-Postgres-Schema/postgres/schema.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- PostgreSQL database dump 3 | -- 4 | 5 | -- Dumped from database version 13.2 (Debian 13.2-1.pgdg100+1) 6 | -- Dumped by pg_dump version 13.2 7 | 8 | -- Started on 2021-05-06 14:00:59 9 | 10 | SET statement_timeout = 0; 11 | SET lock_timeout = 0; 12 | SET idle_in_transaction_session_timeout = 0; 13 | SET client_encoding = 'UTF8'; 14 | SET standard_conforming_strings = on; 15 | SELECT pg_catalog.set_config('search_path', '', false); 16 | SET check_function_bodies = false; 17 | SET xmloption = content; 18 | SET client_min_messages = warning; 19 | SET row_security = off; 20 | 21 | SET default_tablespace = ''; 22 | 23 | SET default_table_access_method = heap; 24 | 25 | CREATE TABLE public.temperature_data ( 26 | id integer NOT NULL, 27 | device character varying, 28 | container character varying, 29 | temperature integer, 30 | created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL 31 | ); 32 | 33 | 34 | ALTER TABLE public.temperature_data ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY ( 35 | SEQUENCE NAME public.temp_data_id_seq 36 | START WITH 1 37 | INCREMENT BY 1 38 | NO MINVALUE 39 | NO MAXVALUE 40 | CACHE 1 41 | ); 42 | 43 | ALTER TABLE ONLY public.temperature_data 44 | ADD CONSTRAINT data_pkey PRIMARY KEY (id); 45 | 46 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/16-PostgREST/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/16-PostgREST/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/16-PostgREST/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/16-PostgREST/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | container_name: dev1 5 | build: ./dev1/ 6 | ports: 7 | - "5000:5000" 8 | volumes: 9 | - type: volume 10 | source: dev1-vol 11 | target: /app 12 | nodered: 13 | container_name: nodered 14 | build: ./nodered/ 15 | ports: 16 | - "1880:1880" 17 | volumes: 18 | - type: volume 19 | source: nodered-vol 20 | target: /data 21 | environment: 22 | - INFLUXDB_TOKEN=mtcderektoken 23 | influxdb: 24 | container_name: influxdb 25 | build: ./influxdb/ 26 | ports: 27 | - "8086:8086" 28 | volumes: 29 | - type: volume 30 | source: influxdb-vol 31 | target: /var/lib/influxdb2 32 | environment: 33 | - DOCKER_INFLUXDB_INIT_MODE=setup 34 | - DOCKER_INFLUXDB_INIT_USERNAME=mtcderek 35 | - DOCKER_INFLUXDB_INIT_PASSWORD=mtcderek 36 | - DOCKER_INFLUXDB_INIT_ORG=mtc 37 | - DOCKER_INFLUXDB_INIT_BUCKET=mtcbucket 38 | - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=mtcderektoken 39 | grafana: 40 | container_name: grafana 41 | build: ./grafana/ 42 | environment: 43 | - GF_SECURITY_ADMIN_USER=mtcderek 44 | - GF_SECURITY_ADMIN_PASSWORD=mtcderek 45 | - INFLUXDB_TOKEN=mtcderektoken 46 | ports: 47 | - "3000:3000" 48 | volumes: 49 | - type: volume 50 | source: grafana-vol 51 | target: /var/lib/grafana 52 | postgres: 53 | container_name: postgres 54 | build: ./postgres/ 55 | ports: 56 | - "5432:5432" 57 | volumes: 58 | - type: volume 59 | source: postgres-vol 60 | target: /var/lib/postgresql/data/ 61 | environment: 62 | - POSTGRES_USER=mtcderek 63 | - POSTGRES_PASSWORD=mtcderek 64 | - POSTGRES_DB=mtcdb 65 | postgrest: 66 | container_name: postgrest 67 | image: postgrest/postgrest 68 | ports: 69 | - "4000:3000" 70 | environment: 71 | - PGRST_DB_URI=postgres://mtcderek:mtcderek@postgres:5432/mtcdb 72 | - PGRST_DB_ANON_ROLE=mtcderek 73 | - PGRST_DB_SCHEMA=public 74 | volumes: 75 | dev1-vol: {} 76 | nodered-vol: {} 77 | influxdb-vol: {} 78 | grafana-vol: {} 79 | postgres-vol: {} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/16-PostgREST/grafana/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM grafana/grafana 2 | COPY datasource.yml /etc/grafana/provisioning/datasources 3 | COPY dashboards/ /etc/grafana/provisioning/dashboards 4 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/16-PostgREST/grafana/dashboards/dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | providers: 3 | - name: 'Temperature' 4 | orgId: 1 5 | folder: 'new dashboards' 6 | type: file 7 | disableDeletion: false 8 | allowUiUpdates: false 9 | options: 10 | path: /etc/grafana/provisioning/dashboards 11 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/16-PostgREST/grafana/datasource.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | datasources: 4 | - name: influxdb 5 | type: influxdb 6 | access: proxy 7 | url: http://influxdb:8086 8 | editable: true 9 | secureJsonData: 10 | token: $INFLUXDB_TOKEN 11 | jsonData: 12 | version: Flux 13 | organization: mtc 14 | defaultBucket: mtcbucket -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/16-PostgREST/influxdb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM influxdb 2 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:8086 || nc -zv localhost 8086 || exit 1 -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/16-PostgREST/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | RUN npm install node-red-contrib-influxdb 4 | 5 | COPY ./settings.js /data/settings.js 6 | COPY ./flows_cred.json /data/flows_cred.json 7 | COPY ./flows.json /data/flows.json 8 | 9 | 10 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/16-PostgREST/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [{"id":"f6f2187d.f17ca8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"8c2bb514.1d2198","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"influxdb","usetls":false,"tls":"","influxdbVersion":"2.0","url":"http://influxdb:8086","rejectUnauthorized":true},{"id":"9d41cfd6.5fe44","type":"inject","z":"f6f2187d.f17ca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":320,"y":400,"wires":[["10d047b2.ab2c38"]]},{"id":"10d047b2.ab2c38","type":"http request","z":"f6f2187d.f17ca8","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://dev1:5000","tls":"","persist":false,"proxy":"","authType":"","x":560,"y":400,"wires":[["4c7a1fb7.c1aa9","220b7260.eab46e"]]},{"id":"4c7a1fb7.c1aa9","type":"debug","z":"f6f2187d.f17ca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":810,"y":400,"wires":[]},{"id":"a536e7c7.4cb5a8","type":"influxdb out","z":"f6f2187d.f17ca8","influxdb":"8c2bb514.1d2198","name":"influxdb","measurement":"data","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"mtc","bucket":"mtcbucket","x":800,"y":500,"wires":[]},{"id":"220b7260.eab46e","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n [{\n temp: msg.payload.data.temp,\n },\n {\n device: msg.payload.data.device,\n name: msg.payload.data.name\n }],\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":500,"wires":[["a536e7c7.4cb5a8","4c7a1fb7.c1aa9"]]}] -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/16-PostgREST/nodered/flows_cred.json: -------------------------------------------------------------------------------- 1 | {"8c2bb514.1d2198":{"token":"mtcderektoken"}} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/16-PostgREST/postgres/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM postgres:13 2 | 3 | COPY schema.sql /docker-entrypoint-initdb.d/ -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/16-PostgREST/postgres/schema.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- PostgreSQL database dump 3 | -- 4 | 5 | -- Dumped from database version 13.2 (Debian 13.2-1.pgdg100+1) 6 | -- Dumped by pg_dump version 13.2 7 | 8 | -- Started on 2021-05-06 14:00:59 9 | 10 | SET statement_timeout = 0; 11 | SET lock_timeout = 0; 12 | SET idle_in_transaction_session_timeout = 0; 13 | SET client_encoding = 'UTF8'; 14 | SET standard_conforming_strings = on; 15 | SELECT pg_catalog.set_config('search_path', '', false); 16 | SET check_function_bodies = false; 17 | SET xmloption = content; 18 | SET client_min_messages = warning; 19 | SET row_security = off; 20 | 21 | SET default_tablespace = ''; 22 | 23 | SET default_table_access_method = heap; 24 | 25 | CREATE TABLE public.temperature_data ( 26 | id integer NOT NULL, 27 | device character varying, 28 | container character varying, 29 | temperature integer, 30 | created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL 31 | ); 32 | 33 | 34 | ALTER TABLE public.temperature_data ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY ( 35 | SEQUENCE NAME public.temp_data_id_seq 36 | START WITH 1 37 | INCREMENT BY 1 38 | NO MINVALUE 39 | NO MAXVALUE 40 | CACHE 1 41 | ); 42 | 43 | ALTER TABLE ONLY public.temperature_data 44 | ADD CONSTRAINT data_pkey PRIMARY KEY (id); 45 | 46 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/17-PostgREST-NodeRED/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/17-PostgREST-NodeRED/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/17-PostgREST-NodeRED/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/17-PostgREST-NodeRED/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | container_name: dev1 5 | build: ./dev1/ 6 | ports: 7 | - "5000:5000" 8 | volumes: 9 | - type: volume 10 | source: dev1-vol 11 | target: /app 12 | nodered: 13 | container_name: nodered 14 | build: ./nodered/ 15 | ports: 16 | - "1880:1880" 17 | volumes: 18 | - type: volume 19 | source: nodered-vol 20 | target: /data 21 | environment: 22 | - INFLUXDB_TOKEN=mtcderektoken 23 | influxdb: 24 | container_name: influxdb 25 | build: ./influxdb/ 26 | ports: 27 | - "8086:8086" 28 | volumes: 29 | - type: volume 30 | source: influxdb-vol 31 | target: /var/lib/influxdb2 32 | environment: 33 | - DOCKER_INFLUXDB_INIT_MODE=setup 34 | - DOCKER_INFLUXDB_INIT_USERNAME=mtcderek 35 | - DOCKER_INFLUXDB_INIT_PASSWORD=mtcderek 36 | - DOCKER_INFLUXDB_INIT_ORG=mtc 37 | - DOCKER_INFLUXDB_INIT_BUCKET=mtcbucket 38 | - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=mtcderektoken 39 | grafana: 40 | container_name: grafana 41 | build: ./grafana/ 42 | environment: 43 | - GF_SECURITY_ADMIN_USER=mtcderek 44 | - GF_SECURITY_ADMIN_PASSWORD=mtcderek 45 | - INFLUXDB_TOKEN=mtcderektoken 46 | ports: 47 | - "3000:3000" 48 | volumes: 49 | - type: volume 50 | source: grafana-vol 51 | target: /var/lib/grafana 52 | postgres: 53 | container_name: postgres 54 | build: ./postgres/ 55 | ports: 56 | - "5432:5432" 57 | volumes: 58 | - type: volume 59 | source: postgres-vol 60 | target: /var/lib/postgresql/data/ 61 | environment: 62 | - POSTGRES_USER=mtcderek 63 | - POSTGRES_PASSWORD=mtcderek 64 | - POSTGRES_DB=mtcdb 65 | postgrest: 66 | container_name: postgrest 67 | image: postgrest/postgrest 68 | ports: 69 | - "4000:3000" 70 | environment: 71 | - PGRST_DB_URI=postgres://mtcderek:mtcderek@postgres:5432/mtcdb 72 | - PGRST_DB_ANON_ROLE=mtcderek 73 | volumes: 74 | dev1-vol: {} 75 | nodered-vol: {} 76 | influxdb-vol: {} 77 | grafana-vol: {} 78 | postgres-vol: {} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/17-PostgREST-NodeRED/grafana/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM grafana/grafana 2 | COPY datasource.yml /etc/grafana/provisioning/datasources 3 | COPY dashboards/ /etc/grafana/provisioning/dashboards 4 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/17-PostgREST-NodeRED/grafana/dashboards/dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | providers: 3 | - name: 'Temperature' 4 | orgId: 1 5 | folder: 'new dashboards' 6 | type: file 7 | disableDeletion: false 8 | allowUiUpdates: false 9 | options: 10 | path: /etc/grafana/provisioning/dashboards 11 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/17-PostgREST-NodeRED/grafana/datasource.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | datasources: 4 | - name: influxdb 5 | type: influxdb 6 | access: proxy 7 | url: http://influxdb:8086 8 | editable: true 9 | secureJsonData: 10 | token: $INFLUXDB_TOKEN 11 | jsonData: 12 | version: Flux 13 | organization: mtc 14 | defaultBucket: mtcbucket -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/17-PostgREST-NodeRED/influxdb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM influxdb 2 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:8086 || nc -zv localhost 8086 || exit 1 -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/17-PostgREST-NodeRED/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | RUN npm install node-red-contrib-influxdb 4 | 5 | COPY ./settings.js /data/settings.js 6 | COPY ./flows_cred.json /data/flows_cred.json 7 | COPY ./flows.json /data/flows.json 8 | 9 | 10 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/17-PostgREST-NodeRED/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [{"id":"f6f2187d.f17ca8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"8c2bb514.1d2198","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"influxdb","usetls":false,"tls":"","influxdbVersion":"2.0","url":"http://influxdb:8086","rejectUnauthorized":true},{"id":"9d41cfd6.5fe44","type":"inject","z":"f6f2187d.f17ca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":320,"y":400,"wires":[["10d047b2.ab2c38"]]},{"id":"10d047b2.ab2c38","type":"http request","z":"f6f2187d.f17ca8","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://dev1:5000","tls":"","persist":false,"proxy":"","authType":"","x":560,"y":400,"wires":[["686d18c1.2ec2d8","220b7260.eab46e"]]},{"id":"4c7a1fb7.c1aa9","type":"debug","z":"f6f2187d.f17ca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":790,"y":400,"wires":[]},{"id":"a536e7c7.4cb5a8","type":"influxdb out","z":"f6f2187d.f17ca8","influxdb":"8c2bb514.1d2198","name":"influxdb","measurement":"data","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"mtc","bucket":"mtcbucket","x":800,"y":500,"wires":[]},{"id":"220b7260.eab46e","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n [{\n temp: msg.payload.data.temp,\n },\n {\n device: msg.payload.data.device,\n name: msg.payload.data.container\n }],\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":500,"wires":[["a536e7c7.4cb5a8","4c7a1fb7.c1aa9"]]},{"id":"686d18c1.2ec2d8","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n{\n \"device\": msg.payload.data.device,\n \"container\": msg.payload.data.container,\n \"temperature\": msg.payload.data.temp\n}\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":580,"y":300,"wires":[["b56a527e.e41dc"]]},{"id":"b56a527e.e41dc","type":"http request","z":"f6f2187d.f17ca8","name":"postgrest","method":"POST","ret":"txt","paytoqs":"ignore","url":"http://postgrest:3000/temperature_data","tls":"","persist":false,"proxy":"","authType":"","x":790,"y":300,"wires":[["4c7a1fb7.c1aa9"]]}] -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/17-PostgREST-NodeRED/nodered/flows_cred.json: -------------------------------------------------------------------------------- 1 | {"8c2bb514.1d2198":{"token":"mtcderektoken"}} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/17-PostgREST-NodeRED/postgres/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM postgres:13 2 | 3 | COPY schema.sql /docker-entrypoint-initdb.d/ -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/17-PostgREST-NodeRED/postgres/schema.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- PostgreSQL database dump 3 | -- 4 | 5 | -- Dumped from database version 13.2 (Debian 13.2-1.pgdg100+1) 6 | -- Dumped by pg_dump version 13.2 7 | 8 | -- Started on 2021-05-06 14:00:59 9 | 10 | SET statement_timeout = 0; 11 | SET lock_timeout = 0; 12 | SET idle_in_transaction_session_timeout = 0; 13 | SET client_encoding = 'UTF8'; 14 | SET standard_conforming_strings = on; 15 | SELECT pg_catalog.set_config('search_path', '', false); 16 | SET check_function_bodies = false; 17 | SET xmloption = content; 18 | SET client_min_messages = warning; 19 | SET row_security = off; 20 | 21 | SET default_tablespace = ''; 22 | 23 | SET default_table_access_method = heap; 24 | 25 | CREATE TABLE public.temperature_data ( 26 | id integer NOT NULL, 27 | device character varying, 28 | container character varying, 29 | temperature integer, 30 | created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL 31 | ); 32 | 33 | 34 | ALTER TABLE public.temperature_data ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY ( 35 | SEQUENCE NAME public.temp_data_id_seq 36 | START WITH 1 37 | INCREMENT BY 1 38 | NO MINVALUE 39 | NO MAXVALUE 40 | CACHE 1 41 | ); 42 | 43 | ALTER TABLE ONLY public.temperature_data 44 | ADD CONSTRAINT data_pkey PRIMARY KEY (id); 45 | 46 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/18-Grafana-Postgres/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/18-Grafana-Postgres/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/18-Grafana-Postgres/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/18-Grafana-Postgres/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | container_name: dev1 5 | build: ./dev1/ 6 | ports: 7 | - "5000:5000" 8 | volumes: 9 | - type: volume 10 | source: dev1-vol 11 | target: /app 12 | nodered: 13 | container_name: nodered 14 | build: ./nodered/ 15 | ports: 16 | - "1880:1880" 17 | volumes: 18 | - type: volume 19 | source: nodered-vol 20 | target: /data 21 | environment: 22 | - INFLUXDB_TOKEN=mtcderektoken 23 | influxdb: 24 | container_name: influxdb 25 | build: ./influxdb/ 26 | ports: 27 | - "8086:8086" 28 | volumes: 29 | - type: volume 30 | source: influxdb-vol 31 | target: /var/lib/influxdb2 32 | environment: 33 | - DOCKER_INFLUXDB_INIT_MODE=setup 34 | - DOCKER_INFLUXDB_INIT_USERNAME=mtcderek 35 | - DOCKER_INFLUXDB_INIT_PASSWORD=mtcderek 36 | - DOCKER_INFLUXDB_INIT_ORG=mtc 37 | - DOCKER_INFLUXDB_INIT_BUCKET=mtcbucket 38 | - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=mtcderektoken 39 | grafana: 40 | container_name: grafana 41 | build: ./grafana/ 42 | environment: 43 | - GF_SECURITY_ADMIN_USER=mtcderek 44 | - GF_SECURITY_ADMIN_PASSWORD=mtcderek 45 | - INFLUXDB_TOKEN=mtcderektoken 46 | ports: 47 | - "3000:3000" 48 | volumes: 49 | - type: volume 50 | source: grafana-vol 51 | target: /var/lib/grafana 52 | postgres: 53 | container_name: postgres 54 | build: ./postgres/ 55 | ports: 56 | - "5432:5432" 57 | volumes: 58 | - type: volume 59 | source: postgres-vol 60 | target: /var/lib/postgresql/data/ 61 | environment: 62 | - POSTGRES_USER=mtcderek 63 | - POSTGRES_PASSWORD=mtcderek 64 | - POSTGRES_DB=mtcdb 65 | postgrest: 66 | container_name: postgrest 67 | image: postgrest/postgrest 68 | ports: 69 | - "4000:3000" 70 | environment: 71 | - PGRST_DB_URI=postgres://mtcderek:mtcderek@postgres:5432/mtcdb 72 | - PGRST_DB_ANON_ROLE=mtcderek 73 | volumes: 74 | dev1-vol: {} 75 | nodered-vol: {} 76 | influxdb-vol: {} 77 | grafana-vol: {} 78 | postgres-vol: {} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/18-Grafana-Postgres/grafana/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM grafana/grafana 2 | COPY datasource.yml /etc/grafana/provisioning/datasources 3 | COPY dashboards/ /etc/grafana/provisioning/dashboards 4 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/18-Grafana-Postgres/grafana/dashboards/dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | providers: 3 | - name: 'Temperature' 4 | orgId: 1 5 | folder: 'new dashboards' 6 | type: file 7 | disableDeletion: false 8 | allowUiUpdates: false 9 | options: 10 | path: /etc/grafana/provisioning/dashboards 11 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/18-Grafana-Postgres/grafana/datasource.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | datasources: 4 | - name: influxdb 5 | type: influxdb 6 | access: proxy 7 | url: http://influxdb:8086 8 | editable: true 9 | secureJsonData: 10 | token: $INFLUXDB_TOKEN 11 | jsonData: 12 | version: Flux 13 | organization: mtc 14 | defaultBucket: mtcbucket 15 | - name: postgres 16 | type: postgres 17 | access: proxy 18 | url: postgres:5432 19 | editable: true 20 | user: mtcderek 21 | database: mtcdb 22 | jsonData: 23 | postgresVersion: 1200 24 | sslmode: "disable" 25 | secureJsonData: 26 | password: mtcderek 27 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/18-Grafana-Postgres/influxdb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM influxdb 2 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:8086 || nc -zv localhost 8086 || exit 1 -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/18-Grafana-Postgres/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | RUN npm install node-red-contrib-influxdb 4 | 5 | COPY ./settings.js /data/settings.js 6 | COPY ./flows_cred.json /data/flows_cred.json 7 | COPY ./flows.json /data/flows.json 8 | 9 | 10 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/18-Grafana-Postgres/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [{"id":"f6f2187d.f17ca8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"8c2bb514.1d2198","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"influxdb","usetls":false,"tls":"","influxdbVersion":"2.0","url":"http://influxdb:8086","rejectUnauthorized":true},{"id":"9d41cfd6.5fe44","type":"inject","z":"f6f2187d.f17ca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":320,"y":400,"wires":[["10d047b2.ab2c38"]]},{"id":"10d047b2.ab2c38","type":"http request","z":"f6f2187d.f17ca8","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://dev1:5000","tls":"","persist":false,"proxy":"","authType":"","x":560,"y":400,"wires":[["686d18c1.2ec2d8","220b7260.eab46e"]]},{"id":"4c7a1fb7.c1aa9","type":"debug","z":"f6f2187d.f17ca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":790,"y":400,"wires":[]},{"id":"a536e7c7.4cb5a8","type":"influxdb out","z":"f6f2187d.f17ca8","influxdb":"8c2bb514.1d2198","name":"influxdb","measurement":"data","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"mtc","bucket":"mtcbucket","x":800,"y":500,"wires":[]},{"id":"220b7260.eab46e","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n [{\n temp: msg.payload.data.temp,\n },\n {\n device: msg.payload.data.device,\n name: msg.payload.data.container\n }],\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":500,"wires":[["a536e7c7.4cb5a8","4c7a1fb7.c1aa9"]]},{"id":"686d18c1.2ec2d8","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n{\n \"device\": msg.payload.data.device,\n \"container\": msg.payload.data.container,\n \"temperature\": msg.payload.data.temp\n}\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":580,"y":300,"wires":[["b56a527e.e41dc"]]},{"id":"b56a527e.e41dc","type":"http request","z":"f6f2187d.f17ca8","name":"postgrest","method":"POST","ret":"txt","paytoqs":"ignore","url":"http://postgrest:3000/temperature_data","tls":"","persist":false,"proxy":"","authType":"","x":790,"y":300,"wires":[["4c7a1fb7.c1aa9"]]}] -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/18-Grafana-Postgres/nodered/flows_cred.json: -------------------------------------------------------------------------------- 1 | {"8c2bb514.1d2198":{"token":"mtcderektoken"}} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/18-Grafana-Postgres/postgres/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM postgres:13 2 | 3 | COPY schema.sql /docker-entrypoint-initdb.d/ -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/18-Grafana-Postgres/postgres/schema.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- PostgreSQL database dump 3 | -- 4 | 5 | -- Dumped from database version 13.2 (Debian 13.2-1.pgdg100+1) 6 | -- Dumped by pg_dump version 13.2 7 | 8 | -- Started on 2021-05-06 14:00:59 9 | 10 | SET statement_timeout = 0; 11 | SET lock_timeout = 0; 12 | SET idle_in_transaction_session_timeout = 0; 13 | SET client_encoding = 'UTF8'; 14 | SET standard_conforming_strings = on; 15 | SELECT pg_catalog.set_config('search_path', '', false); 16 | SET check_function_bodies = false; 17 | SET xmloption = content; 18 | SET client_min_messages = warning; 19 | SET row_security = off; 20 | 21 | SET default_tablespace = ''; 22 | 23 | SET default_table_access_method = heap; 24 | 25 | CREATE TABLE public.temperature_data ( 26 | id integer NOT NULL, 27 | device character varying, 28 | container character varying, 29 | temperature integer, 30 | created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL 31 | ); 32 | 33 | 34 | ALTER TABLE public.temperature_data ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY ( 35 | SEQUENCE NAME public.temp_data_id_seq 36 | START WITH 1 37 | INCREMENT BY 1 38 | NO MINVALUE 39 | NO MAXVALUE 40 | CACHE 1 41 | ); 42 | 43 | ALTER TABLE ONLY public.temperature_data 44 | ADD CONSTRAINT data_pkey PRIMARY KEY (id); 45 | 46 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/19-Docker-Networking/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/19-Docker-Networking/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/19-Docker-Networking/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/19-Docker-Networking/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | image: registry.gitlab.com/mtc-infra/dev1:latest 5 | networks: 6 | - backend 7 | volumes: 8 | - type: volume 9 | source: dev1-vol 10 | target: /app 11 | nodered: 12 | container_name: nodered 13 | build: ./nodered/ 14 | networks: 15 | - backend 16 | ports: 17 | - "1880:1880" 18 | volumes: 19 | - type: volume 20 | source: nodered-vol 21 | target: /data 22 | environment: 23 | - INFLUXDB_TOKEN=mtcderektoken 24 | influxdb: 25 | container_name: influxdb 26 | build: ./influxdb/ 27 | networks: 28 | - backend 29 | volumes: 30 | - type: volume 31 | source: influxdb-vol 32 | target: /var/lib/influxdb2 33 | environment: 34 | - DOCKER_INFLUXDB_INIT_MODE=setup 35 | - DOCKER_INFLUXDB_INIT_USERNAME=mtcderek 36 | - DOCKER_INFLUXDB_INIT_PASSWORD=mtcderek 37 | - DOCKER_INFLUXDB_INIT_ORG=mtc 38 | - DOCKER_INFLUXDB_INIT_BUCKET=mtcbucket 39 | - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=mtcderektoken 40 | grafana: 41 | container_name: grafana 42 | build: ./grafana/ 43 | environment: 44 | - GF_SECURITY_ADMIN_USER=mtcderek 45 | - GF_SECURITY_ADMIN_PASSWORD=mtcderek 46 | - INFLUXDB_TOKEN=mtcderektoken 47 | networks: 48 | - frontend 49 | - backend 50 | - db 51 | ports: 52 | - "3000:3000" 53 | volumes: 54 | - type: volume 55 | source: grafana-vol 56 | target: /var/lib/grafana 57 | postgres: 58 | container_name: postgres 59 | build: ./postgres/ 60 | networks: 61 | - db 62 | volumes: 63 | - type: volume 64 | source: postgres-vol 65 | target: /var/lib/postgresql/data/ 66 | environment: 67 | - POSTGRES_USER=mtcderek 68 | - POSTGRES_PASSWORD=mtcderek 69 | - POSTGRES_DB=mtcdb 70 | postgrest: 71 | container_name: postgrest 72 | image: postgrest/postgrest 73 | networks: 74 | - backend 75 | - db 76 | environment: 77 | - PGRST_DB_URI=postgres://mtcderek:mtcderek@postgres:5432/mtcdb 78 | - PGRST_DB_ANON_ROLE=mtcderek 79 | volumes: 80 | dev1-vol: {} 81 | nodered-vol: {} 82 | influxdb-vol: {} 83 | grafana-vol: {} 84 | postgres-vol: {} 85 | networks: 86 | frontend: {} 87 | backend: {} 88 | db: {} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/19-Docker-Networking/grafana/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM grafana/grafana 2 | COPY datasource.yml /etc/grafana/provisioning/datasources 3 | COPY dashboards/ /etc/grafana/provisioning/dashboards 4 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/19-Docker-Networking/grafana/dashboards/dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | providers: 3 | - name: 'Temperature' 4 | orgId: 1 5 | folder: 'new dashboards' 6 | type: file 7 | disableDeletion: false 8 | allowUiUpdates: false 9 | options: 10 | path: /etc/grafana/provisioning/dashboards 11 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/19-Docker-Networking/grafana/datasource.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | datasources: 4 | - name: influxdb 5 | type: influxdb 6 | access: proxy 7 | url: http://influxdb:8086 8 | editable: true 9 | secureJsonData: 10 | token: $INFLUXDB_TOKEN 11 | jsonData: 12 | version: Flux 13 | organization: mtc 14 | defaultBucket: mtcbucket 15 | - name: postgres 16 | type: postgres 17 | access: proxy 18 | url: postgres:5432 19 | editable: true 20 | user: mtcderek 21 | database: mtcdb 22 | jsonData: 23 | postgresVersion: 1200 24 | sslmode: "disable" 25 | secureJsonData: 26 | password: mtcderek 27 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/19-Docker-Networking/influxdb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM influxdb 2 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:8086 || nc -zv localhost 8086 || exit 1 -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/19-Docker-Networking/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | RUN npm install node-red-contrib-influxdb 4 | 5 | COPY ./settings.js /data/settings.js 6 | COPY ./flows_cred.json /data/flows_cred.json 7 | COPY ./flows.json /data/flows.json 8 | 9 | 10 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/19-Docker-Networking/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [{"id":"f6f2187d.f17ca8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"8c2bb514.1d2198","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"influxdb","usetls":false,"tls":"","influxdbVersion":"2.0","url":"http://influxdb:8086","rejectUnauthorized":true},{"id":"9d41cfd6.5fe44","type":"inject","z":"f6f2187d.f17ca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":320,"y":400,"wires":[["10d047b2.ab2c38"]]},{"id":"10d047b2.ab2c38","type":"http request","z":"f6f2187d.f17ca8","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://dev1:5000","tls":"","persist":false,"proxy":"","authType":"","x":560,"y":400,"wires":[["686d18c1.2ec2d8","220b7260.eab46e"]]},{"id":"4c7a1fb7.c1aa9","type":"debug","z":"f6f2187d.f17ca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":790,"y":400,"wires":[]},{"id":"a536e7c7.4cb5a8","type":"influxdb out","z":"f6f2187d.f17ca8","influxdb":"8c2bb514.1d2198","name":"influxdb","measurement":"data","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"mtc","bucket":"mtcbucket","x":800,"y":500,"wires":[]},{"id":"220b7260.eab46e","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n [{\n temp: msg.payload.data.temp,\n },\n {\n device: msg.payload.data.device,\n name: msg.payload.data.container\n }],\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":500,"wires":[["a536e7c7.4cb5a8","4c7a1fb7.c1aa9"]]},{"id":"686d18c1.2ec2d8","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n{\n \"device\": msg.payload.data.device,\n \"container\": msg.payload.data.container,\n \"temperature\": msg.payload.data.temp\n}\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":580,"y":300,"wires":[["b56a527e.e41dc"]]},{"id":"b56a527e.e41dc","type":"http request","z":"f6f2187d.f17ca8","name":"postgrest","method":"POST","ret":"txt","paytoqs":"ignore","url":"http://postgrest:3000/temperature_data","tls":"","persist":false,"proxy":"","authType":"","x":790,"y":300,"wires":[["4c7a1fb7.c1aa9"]]}] -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/19-Docker-Networking/nodered/flows_cred.json: -------------------------------------------------------------------------------- 1 | {"8c2bb514.1d2198":{"token":"mtcderektoken"}} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/19-Docker-Networking/postgres/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM postgres:13 2 | 3 | COPY schema.sql /docker-entrypoint-initdb.d/ -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/19-Docker-Networking/postgres/schema.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- PostgreSQL database dump 3 | -- 4 | 5 | -- Dumped from database version 13.2 (Debian 13.2-1.pgdg100+1) 6 | -- Dumped by pg_dump version 13.2 7 | 8 | -- Started on 2021-05-06 14:00:59 9 | 10 | SET statement_timeout = 0; 11 | SET lock_timeout = 0; 12 | SET idle_in_transaction_session_timeout = 0; 13 | SET client_encoding = 'UTF8'; 14 | SET standard_conforming_strings = on; 15 | SELECT pg_catalog.set_config('search_path', '', false); 16 | SET check_function_bodies = false; 17 | SET xmloption = content; 18 | SET client_min_messages = warning; 19 | SET row_security = off; 20 | 21 | SET default_tablespace = ''; 22 | 23 | SET default_table_access_method = heap; 24 | 25 | CREATE TABLE public.temperature_data ( 26 | id integer NOT NULL, 27 | device character varying, 28 | container character varying, 29 | temperature integer, 30 | created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL 31 | ); 32 | 33 | 34 | ALTER TABLE public.temperature_data ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY ( 35 | SEQUENCE NAME public.temp_data_id_seq 36 | START WITH 1 37 | INCREMENT BY 1 38 | NO MINVALUE 39 | NO MAXVALUE 40 | CACHE 1 41 | ); 42 | 43 | ALTER TABLE ONLY public.temperature_data 44 | ADD CONSTRAINT data_pkey PRIMARY KEY (id); 45 | 46 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/20-Docker-Compose-Exec/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/20-Docker-Compose-Exec/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/20-Docker-Compose-Exec/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/20-Docker-Compose-Exec/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | container_name: dev1 5 | build: ./dev1/ 6 | networks: 7 | - backend 8 | volumes: 9 | - type: volume 10 | source: dev1-vol 11 | target: /app 12 | nodered: 13 | container_name: nodered 14 | build: ./nodered/ 15 | networks: 16 | - backend 17 | ports: 18 | - "1880:1880" 19 | volumes: 20 | - type: volume 21 | source: nodered-vol 22 | target: /data 23 | environment: 24 | - INFLUXDB_TOKEN=mtcderektoken 25 | influxdb: 26 | container_name: influxdb 27 | build: ./influxdb/ 28 | networks: 29 | - backend 30 | volumes: 31 | - type: volume 32 | source: influxdb-vol 33 | target: /var/lib/influxdb2 34 | environment: 35 | - DOCKER_INFLUXDB_INIT_MODE=setup 36 | - DOCKER_INFLUXDB_INIT_USERNAME=mtcderek 37 | - DOCKER_INFLUXDB_INIT_PASSWORD=mtcderek 38 | - DOCKER_INFLUXDB_INIT_ORG=mtc 39 | - DOCKER_INFLUXDB_INIT_BUCKET=mtcbucket 40 | - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=mtcderektoken 41 | grafana: 42 | container_name: grafana 43 | build: ./grafana/ 44 | environment: 45 | - GF_SECURITY_ADMIN_USER=mtcderek 46 | - GF_SECURITY_ADMIN_PASSWORD=mtcderek 47 | - INFLUXDB_TOKEN=mtcderektoken 48 | networks: 49 | - frontend 50 | - backend 51 | - db 52 | ports: 53 | - "3000:3000" 54 | volumes: 55 | - type: volume 56 | source: grafana-vol 57 | target: /var/lib/grafana 58 | postgres: 59 | container_name: postgres 60 | build: ./postgres/ 61 | networks: 62 | - db 63 | volumes: 64 | - type: volume 65 | source: postgres-vol 66 | target: /var/lib/postgresql/data/ 67 | environment: 68 | - POSTGRES_USER=mtcderek 69 | - POSTGRES_PASSWORD=mtcderek 70 | - POSTGRES_DB=mtcdb 71 | postgrest: 72 | container_name: postgrest 73 | image: postgrest/postgrest 74 | networks: 75 | - backend 76 | - db 77 | environment: 78 | - PGRST_DB_URI=postgres://mtcderek:mtcderek@postgres:5432/mtcdb 79 | - PGRST_DB_ANON_ROLE=mtcderek 80 | volumes: 81 | dev1-vol: {} 82 | nodered-vol: {} 83 | influxdb-vol: {} 84 | grafana-vol: {} 85 | postgres-vol: {} 86 | networks: 87 | frontend: {} 88 | backend: {} 89 | db: {} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/20-Docker-Compose-Exec/grafana/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM grafana/grafana 2 | COPY datasource.yml /etc/grafana/provisioning/datasources 3 | COPY dashboards/ /etc/grafana/provisioning/dashboards 4 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/20-Docker-Compose-Exec/grafana/dashboards/dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | providers: 3 | - name: 'Temperature' 4 | orgId: 1 5 | folder: 'new dashboards' 6 | type: file 7 | disableDeletion: false 8 | allowUiUpdates: false 9 | options: 10 | path: /etc/grafana/provisioning/dashboards 11 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/20-Docker-Compose-Exec/grafana/datasource.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | datasources: 4 | - name: influxdb 5 | type: influxdb 6 | access: proxy 7 | url: http://influxdb:8086 8 | editable: true 9 | secureJsonData: 10 | token: $INFLUXDB_TOKEN 11 | jsonData: 12 | version: Flux 13 | organization: mtc 14 | defaultBucket: mtcbucket 15 | - name: postgres 16 | type: postgres 17 | access: proxy 18 | url: postgres:5432 19 | editable: true 20 | user: mtcderek 21 | database: mtcdb 22 | jsonData: 23 | postgresVersion: 1200 24 | sslmode: "disable" 25 | secureJsonData: 26 | password: mtcderek 27 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/20-Docker-Compose-Exec/influxdb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM influxdb 2 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:8086 || nc -zv localhost 8086 || exit 1 -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/20-Docker-Compose-Exec/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | RUN npm install node-red-contrib-influxdb 4 | 5 | COPY ./settings.js /data/settings.js 6 | COPY ./flows_cred.json /data/flows_cred.json 7 | COPY ./flows.json /data/flows.json 8 | 9 | 10 | -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/20-Docker-Compose-Exec/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [{"id":"f6f2187d.f17ca8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"8c2bb514.1d2198","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"influxdb","usetls":false,"tls":"","influxdbVersion":"2.0","url":"http://influxdb:8086","rejectUnauthorized":true},{"id":"9d41cfd6.5fe44","type":"inject","z":"f6f2187d.f17ca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":320,"y":400,"wires":[["10d047b2.ab2c38"]]},{"id":"10d047b2.ab2c38","type":"http request","z":"f6f2187d.f17ca8","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://dev1:5000","tls":"","persist":false,"proxy":"","authType":"","x":560,"y":400,"wires":[["686d18c1.2ec2d8","220b7260.eab46e"]]},{"id":"4c7a1fb7.c1aa9","type":"debug","z":"f6f2187d.f17ca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":790,"y":400,"wires":[]},{"id":"a536e7c7.4cb5a8","type":"influxdb out","z":"f6f2187d.f17ca8","influxdb":"8c2bb514.1d2198","name":"influxdb","measurement":"data","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"mtc","bucket":"mtcbucket","x":800,"y":500,"wires":[]},{"id":"220b7260.eab46e","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n [{\n temp: msg.payload.data.temp,\n },\n {\n device: msg.payload.data.device,\n name: msg.payload.data.container\n }],\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":500,"wires":[["a536e7c7.4cb5a8","4c7a1fb7.c1aa9"]]},{"id":"686d18c1.2ec2d8","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n{\n \"device\": msg.payload.data.device,\n \"container\": msg.payload.data.container,\n \"temperature\": msg.payload.data.temp\n}\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":580,"y":300,"wires":[["b56a527e.e41dc"]]},{"id":"b56a527e.e41dc","type":"http request","z":"f6f2187d.f17ca8","name":"postgrest","method":"POST","ret":"txt","paytoqs":"ignore","url":"http://postgrest:3000/temperature_data","tls":"","persist":false,"proxy":"","authType":"","x":790,"y":300,"wires":[["4c7a1fb7.c1aa9"]]}] -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/20-Docker-Compose-Exec/nodered/flows_cred.json: -------------------------------------------------------------------------------- 1 | {"8c2bb514.1d2198":{"token":"mtcderektoken"}} -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/20-Docker-Compose-Exec/postgres/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM postgres:13 2 | 3 | COPY schema.sql /docker-entrypoint-initdb.d/ -------------------------------------------------------------------------------- /Lesson-Files/02-Docker-Compose/20-Docker-Compose-Exec/postgres/schema.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- PostgreSQL database dump 3 | -- 4 | 5 | -- Dumped from database version 13.2 (Debian 13.2-1.pgdg100+1) 6 | -- Dumped by pg_dump version 13.2 7 | 8 | -- Started on 2021-05-06 14:00:59 9 | 10 | SET statement_timeout = 0; 11 | SET lock_timeout = 0; 12 | SET idle_in_transaction_session_timeout = 0; 13 | SET client_encoding = 'UTF8'; 14 | SET standard_conforming_strings = on; 15 | SELECT pg_catalog.set_config('search_path', '', false); 16 | SET check_function_bodies = false; 17 | SET xmloption = content; 18 | SET client_min_messages = warning; 19 | SET row_security = off; 20 | 21 | SET default_tablespace = ''; 22 | 23 | SET default_table_access_method = heap; 24 | 25 | CREATE TABLE public.temperature_data ( 26 | id integer NOT NULL, 27 | device character varying, 28 | container character varying, 29 | temperature integer, 30 | created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL 31 | ); 32 | 33 | 34 | ALTER TABLE public.temperature_data ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY ( 35 | SEQUENCE NAME public.temp_data_id_seq 36 | START WITH 1 37 | INCREMENT BY 1 38 | NO MINVALUE 39 | NO MAXVALUE 40 | CACHE 1 41 | ); 42 | 43 | ALTER TABLE ONLY public.temperature_data 44 | ADD CONSTRAINT data_pkey PRIMARY KEY (id); 45 | 46 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/01-VPN-Setup/dev1/.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # This file is a template, and might need editing before it works on your project. 2 | # Build a Docker image with CI/CD and push to the GitLab registry. 3 | # Docker-in-Docker documentation: https://docs.gitlab.com/ee/ci/docker/using_docker_build.html 4 | # 5 | # This template uses one generic job with conditional builds 6 | # for the default branch and all other (MR) branches. 7 | docker-build: 8 | # Use the official docker image. 9 | image: docker:latest 10 | stage: build 11 | services: 12 | - docker:dind 13 | before_script: 14 | - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY 15 | # Default branch leaves tag empty (= latest tag) 16 | # All other branches are tagged with the escaped branch name (commit ref slug) 17 | script: 18 | - | 19 | if [[ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]]; then 20 | tag="" 21 | echo "Running on default branch '$CI_DEFAULT_BRANCH': tag = 'latest'" 22 | else 23 | tag=":$CI_COMMIT_REF_SLUG" 24 | echo "Running on branch '$CI_COMMIT_BRANCH': tag = $tag" 25 | fi 26 | - docker build --pull -t "$CI_REGISTRY_IMAGE${tag}" . 27 | - docker push "$CI_REGISTRY_IMAGE${tag}" 28 | # Run this job in a branch where a Dockerfile exists 29 | rules: 30 | - if: $CI_COMMIT_BRANCH 31 | exists: 32 | - Dockerfile -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/01-VPN-Setup/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/01-VPN-Setup/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/01-VPN-Setup/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/01-VPN-Setup/dev1/gitinit.sh: -------------------------------------------------------------------------------- 1 | git init && 2 | git remote add origin https://gitlab.com/mtc-infra/$(echo ${PWD} | awk -F/ '{print $NF}').git && 3 | git add . && 4 | git commit -m "initial" && 5 | git push -u origin master -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/01-VPN-Setup/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | # api: 4 | # container_name: dev1 5 | # image: registry.gitlab.com/mtc-infra/dev1:latest 6 | # networks: 7 | # - backend 8 | # volumes: 9 | # - type: volume 10 | # source: dev1-vol 11 | # target: /app 12 | # nodered: 13 | # container_name: nodered 14 | # build: ./nodered/ 15 | # networks: 16 | # - backend 17 | # ports: 18 | # - "1880:1880" 19 | # volumes: 20 | # - type: volume 21 | # source: nodered-vol 22 | # target: /data 23 | # environment: 24 | # - INFLUXDB_TOKEN=mtcderektoken 25 | # influxdb: 26 | # container_name: influxdb 27 | # image: registry.gitlab.com/mtc-infra/influxdb:latest 28 | # networks: 29 | # - backend 30 | # volumes: 31 | # - type: volume 32 | # source: influxdb-vol 33 | # target: /var/lib/influxdb2 34 | # environment: 35 | # - DOCKER_INFLUXDB_INIT_MODE=setup 36 | # - DOCKER_INFLUXDB_INIT_USERNAME=mtcderek 37 | # - DOCKER_INFLUXDB_INIT_PASSWORD=mtcderek 38 | # - DOCKER_INFLUXDB_INIT_ORG=mtc 39 | # - DOCKER_INFLUXDB_INIT_BUCKET=mtcbucket 40 | # - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=mtcderektoken 41 | # grafana: 42 | # container_name: grafana 43 | # image: registry.gitlab.com/mtc-infra/grafana:latest 44 | # environment: 45 | # - GF_SECURITY_ADMIN_USER=mtcderek 46 | # - GF_SECURITY_ADMIN_PASSWORD=mtcderek 47 | # - INFLUXDB_TOKEN=mtcderektoken 48 | # networks: 49 | # - frontend 50 | # - backend 51 | # - db 52 | # ports: 53 | # - "3000:3000" 54 | # volumes: 55 | # - type: volume 56 | # source: grafana-vol 57 | # target: /var/lib/grafana 58 | # postgres: 59 | # container_name: postgres 60 | # image: registry.gitlab.com/mtc-infra/postgres:latest 61 | # networks: 62 | # - db 63 | # volumes: 64 | # - type: volume 65 | # source: postgres-vol 66 | # target: /var/lib/postgresql/data/ 67 | # environment: 68 | # - POSTGRES_USER=mtcderek 69 | # - POSTGRES_PASSWORD=mtcderek 70 | # - POSTGRES_DB=mtcdb 71 | # postgrest: 72 | # container_name: postgrest 73 | # image: postgrest/postgrest 74 | # networks: 75 | # - backend 76 | # - db 77 | # environment: 78 | # - PGRST_DB_URI=postgres://mtcderek:mtcderek@postgres:5432/mtcdb 79 | # - PGRST_DB_ANON_ROLE=mtcderek 80 | wireguard: 81 | image: ghcr.io/linuxserver/wireguard 82 | container_name: wireguard 83 | environment: 84 | - PUID=1000 85 | - PGID=1000 86 | - TZ=America/Chicago 87 | - PEERS=3 88 | volumes: 89 | - /home/ubuntu/environment/mtc-docker/Public/Lesson-Files/04-Docker-Admin/01-VPN-Setup/wireguard/config:/config 90 | - /lib/modules:/lib/modules 91 | ports: 92 | - 51820:51820/udp 93 | volumes: 94 | dev1-vol: {} 95 | nodered-vol: {} 96 | influxdb-vol: {} 97 | grafana-vol: {} 98 | postgres-vol: {} 99 | networks: 100 | frontend: {} 101 | backend: {} 102 | db: {} -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/01-VPN-Setup/grafana/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM grafana/grafana 2 | COPY datasource.yml /etc/grafana/provisioning/datasources 3 | COPY dashboards/ /etc/grafana/provisioning/dashboards 4 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/01-VPN-Setup/grafana/dashboards/dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | providers: 3 | - name: 'Temperature' 4 | orgId: 1 5 | folder: 'new dashboards' 6 | type: file 7 | disableDeletion: false 8 | allowUiUpdates: false 9 | options: 10 | path: /etc/grafana/provisioning/dashboards 11 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/01-VPN-Setup/grafana/datasource.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | datasources: 4 | - name: influxdb 5 | type: influxdb 6 | access: proxy 7 | url: http://influxdb:8086 8 | editable: true 9 | secureJsonData: 10 | token: $INFLUXDB_TOKEN 11 | jsonData: 12 | version: Flux 13 | organization: mtc 14 | defaultBucket: mtcbucket 15 | - name: postgres 16 | type: postgres 17 | access: proxy 18 | url: postgres:5432 19 | editable: true 20 | user: mtcderek 21 | database: mtcdb 22 | jsonData: 23 | postgresVersion: 1200 24 | sslmode: "disable" 25 | secureJsonData: 26 | password: mtcderek 27 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/01-VPN-Setup/influxdb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM influxdb 2 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:8086 || nc -zv localhost 8086 || exit 1 -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/01-VPN-Setup/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | RUN npm install node-red-contrib-influxdb 4 | 5 | COPY ./settings.js /data/settings.js 6 | COPY ./flows_cred.json /data/flows_cred.json 7 | COPY ./flows.json /data/flows.json 8 | 9 | 10 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/01-VPN-Setup/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [{"id":"f6f2187d.f17ca8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"8c2bb514.1d2198","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"influxdb","usetls":false,"tls":"","influxdbVersion":"2.0","url":"http://influxdb:8086","rejectUnauthorized":true},{"id":"9d41cfd6.5fe44","type":"inject","z":"f6f2187d.f17ca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":320,"y":400,"wires":[["10d047b2.ab2c38"]]},{"id":"10d047b2.ab2c38","type":"http request","z":"f6f2187d.f17ca8","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://dev1:5000","tls":"","persist":false,"proxy":"","authType":"","x":560,"y":400,"wires":[["686d18c1.2ec2d8","220b7260.eab46e"]]},{"id":"4c7a1fb7.c1aa9","type":"debug","z":"f6f2187d.f17ca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":790,"y":400,"wires":[]},{"id":"a536e7c7.4cb5a8","type":"influxdb out","z":"f6f2187d.f17ca8","influxdb":"8c2bb514.1d2198","name":"influxdb","measurement":"data","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"mtc","bucket":"mtcbucket","x":800,"y":500,"wires":[]},{"id":"220b7260.eab46e","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n [{\n temp: msg.payload.data.temp,\n },\n {\n device: msg.payload.data.device,\n name: msg.payload.data.container\n }],\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":500,"wires":[["a536e7c7.4cb5a8","4c7a1fb7.c1aa9"]]},{"id":"686d18c1.2ec2d8","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n{\n \"device\": msg.payload.data.device,\n \"container\": msg.payload.data.container,\n \"temperature\": msg.payload.data.temp\n}\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":580,"y":300,"wires":[["b56a527e.e41dc"]]},{"id":"b56a527e.e41dc","type":"http request","z":"f6f2187d.f17ca8","name":"postgrest","method":"POST","ret":"txt","paytoqs":"ignore","url":"http://postgrest:3000/temperature_data","tls":"","persist":false,"proxy":"","authType":"","x":790,"y":300,"wires":[["4c7a1fb7.c1aa9"]]}] -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/01-VPN-Setup/nodered/flows_cred.json: -------------------------------------------------------------------------------- 1 | {"8c2bb514.1d2198":{"token":"mtcderektoken"}} -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/01-VPN-Setup/postgres/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM postgres:13 2 | 3 | COPY schema.sql /docker-entrypoint-initdb.d/ -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/01-VPN-Setup/postgres/schema.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- PostgreSQL database dump 3 | -- 4 | 5 | -- Dumped from database version 13.2 (Debian 13.2-1.pgdg100+1) 6 | -- Dumped by pg_dump version 13.2 7 | 8 | -- Started on 2021-05-06 14:00:59 9 | 10 | SET statement_timeout = 0; 11 | SET lock_timeout = 0; 12 | SET idle_in_transaction_session_timeout = 0; 13 | SET client_encoding = 'UTF8'; 14 | SET standard_conforming_strings = on; 15 | SELECT pg_catalog.set_config('search_path', '', false); 16 | SET check_function_bodies = false; 17 | SET xmloption = content; 18 | SET client_min_messages = warning; 19 | SET row_security = off; 20 | 21 | SET default_tablespace = ''; 22 | 23 | SET default_table_access_method = heap; 24 | 25 | CREATE TABLE public.temperature_data ( 26 | id integer NOT NULL, 27 | device character varying, 28 | container character varying, 29 | temperature integer, 30 | created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL 31 | ); 32 | 33 | 34 | ALTER TABLE public.temperature_data ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY ( 35 | SEQUENCE NAME public.temp_data_id_seq 36 | START WITH 1 37 | INCREMENT BY 1 38 | NO MINVALUE 39 | NO MAXVALUE 40 | CACHE 1 41 | ); 42 | 43 | ALTER TABLE ONLY public.temperature_data 44 | ADD CONSTRAINT data_pkey PRIMARY KEY (id); 45 | 46 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/02-Linux-Capabilities/dev1/.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # This file is a template, and might need editing before it works on your project. 2 | # Build a Docker image with CI/CD and push to the GitLab registry. 3 | # Docker-in-Docker documentation: https://docs.gitlab.com/ee/ci/docker/using_docker_build.html 4 | # 5 | # This template uses one generic job with conditional builds 6 | # for the default branch and all other (MR) branches. 7 | docker-build: 8 | # Use the official docker image. 9 | image: docker:latest 10 | stage: build 11 | services: 12 | - docker:dind 13 | before_script: 14 | - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY 15 | # Default branch leaves tag empty (= latest tag) 16 | # All other branches are tagged with the escaped branch name (commit ref slug) 17 | script: 18 | - | 19 | if [[ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]]; then 20 | tag="" 21 | echo "Running on default branch '$CI_DEFAULT_BRANCH': tag = 'latest'" 22 | else 23 | tag=":$CI_COMMIT_REF_SLUG" 24 | echo "Running on branch '$CI_COMMIT_BRANCH': tag = $tag" 25 | fi 26 | - docker build --pull -t "$CI_REGISTRY_IMAGE${tag}" . 27 | - docker push "$CI_REGISTRY_IMAGE${tag}" 28 | # Run this job in a branch where a Dockerfile exists 29 | rules: 30 | - if: $CI_COMMIT_BRANCH 31 | exists: 32 | - Dockerfile -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/02-Linux-Capabilities/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/02-Linux-Capabilities/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/02-Linux-Capabilities/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/02-Linux-Capabilities/dev1/gitinit.sh: -------------------------------------------------------------------------------- 1 | git init && 2 | git remote add origin https://gitlab.com/mtc-infra/$(echo ${PWD} | awk -F/ '{print $NF}').git && 3 | git add . && 4 | git commit -m "initial" && 5 | git push -u origin master -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/02-Linux-Capabilities/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | # api: 4 | # container_name: dev1 5 | # image: registry.gitlab.com/mtc-infra/dev1:latest 6 | # networks: 7 | # - backend 8 | # volumes: 9 | # - type: volume 10 | # source: dev1-vol 11 | # target: /app 12 | # nodered: 13 | # container_name: nodered 14 | # build: ./nodered/ 15 | # networks: 16 | # - backend 17 | # ports: 18 | # - "1880:1880" 19 | # volumes: 20 | # - type: volume 21 | # source: nodered-vol 22 | # target: /data 23 | # environment: 24 | # - INFLUXDB_TOKEN=mtcderektoken 25 | # influxdb: 26 | # container_name: influxdb 27 | # image: registry.gitlab.com/mtc-infra/influxdb:latest 28 | # networks: 29 | # - backend 30 | # volumes: 31 | # - type: volume 32 | # source: influxdb-vol 33 | # target: /var/lib/influxdb2 34 | # environment: 35 | # - DOCKER_INFLUXDB_INIT_MODE=setup 36 | # - DOCKER_INFLUXDB_INIT_USERNAME=mtcderek 37 | # - DOCKER_INFLUXDB_INIT_PASSWORD=mtcderek 38 | # - DOCKER_INFLUXDB_INIT_ORG=mtc 39 | # - DOCKER_INFLUXDB_INIT_BUCKET=mtcbucket 40 | # - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=mtcderektoken 41 | # grafana: 42 | # container_name: grafana 43 | # image: registry.gitlab.com/mtc-infra/grafana:latest 44 | # environment: 45 | # - GF_SECURITY_ADMIN_USER=mtcderek 46 | # - GF_SECURITY_ADMIN_PASSWORD=mtcderek 47 | # - INFLUXDB_TOKEN=mtcderektoken 48 | # networks: 49 | # - frontend 50 | # - backend 51 | # - db 52 | # ports: 53 | # - "3000:3000" 54 | # volumes: 55 | # - type: volume 56 | # source: grafana-vol 57 | # target: /var/lib/grafana 58 | # postgres: 59 | # container_name: postgres 60 | # image: registry.gitlab.com/mtc-infra/postgres:latest 61 | # networks: 62 | # - db 63 | # volumes: 64 | # - type: volume 65 | # source: postgres-vol 66 | # target: /var/lib/postgresql/data/ 67 | # environment: 68 | # - POSTGRES_USER=mtcderek 69 | # - POSTGRES_PASSWORD=mtcderek 70 | # - POSTGRES_DB=mtcdb 71 | # postgrest: 72 | # container_name: postgrest 73 | # image: postgrest/postgrest 74 | # networks: 75 | # - backend 76 | # - db 77 | # environment: 78 | # - PGRST_DB_URI=postgres://mtcderek:mtcderek@postgres:5432/mtcdb 79 | # - PGRST_DB_ANON_ROLE=mtcderek 80 | wireguard: 81 | image: ghcr.io/linuxserver/wireguard 82 | container_name: wireguard 83 | cap_add: 84 | - NET_ADMIN 85 | - SYS_MODULE 86 | environment: 87 | - PUID=1000 88 | - PGID=1000 89 | - TZ=America/Chicago 90 | - PEERS=3 91 | volumes: 92 | - /home/ubuntu/environment/mtc-docker/Public/Lesson-Files/04-Docker-Admin/02-Linux-Capabilities/wireguard/config:/config 93 | - /lib/modules:/lib/modules 94 | ports: 95 | - 51820:51820/udp 96 | volumes: 97 | dev1-vol: {} 98 | nodered-vol: {} 99 | influxdb-vol: {} 100 | grafana-vol: {} 101 | postgres-vol: {} 102 | networks: 103 | frontend: {} 104 | backend: {} 105 | db: {} -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/02-Linux-Capabilities/grafana/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM grafana/grafana 2 | COPY datasource.yml /etc/grafana/provisioning/datasources 3 | COPY dashboards/ /etc/grafana/provisioning/dashboards 4 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/02-Linux-Capabilities/grafana/dashboards/dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | providers: 3 | - name: 'Temperature' 4 | orgId: 1 5 | folder: 'new dashboards' 6 | type: file 7 | disableDeletion: false 8 | allowUiUpdates: false 9 | options: 10 | path: /etc/grafana/provisioning/dashboards 11 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/02-Linux-Capabilities/grafana/datasource.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | datasources: 4 | - name: influxdb 5 | type: influxdb 6 | access: proxy 7 | url: http://influxdb:8086 8 | editable: true 9 | secureJsonData: 10 | token: $INFLUXDB_TOKEN 11 | jsonData: 12 | version: Flux 13 | organization: mtc 14 | defaultBucket: mtcbucket 15 | - name: postgres 16 | type: postgres 17 | access: proxy 18 | url: postgres:5432 19 | editable: true 20 | user: mtcderek 21 | database: mtcdb 22 | jsonData: 23 | postgresVersion: 1200 24 | sslmode: "disable" 25 | secureJsonData: 26 | password: mtcderek 27 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/02-Linux-Capabilities/influxdb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM influxdb 2 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:8086 || nc -zv localhost 8086 || exit 1 -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/02-Linux-Capabilities/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | RUN npm install node-red-contrib-influxdb 4 | 5 | COPY ./settings.js /data/settings.js 6 | COPY ./flows_cred.json /data/flows_cred.json 7 | COPY ./flows.json /data/flows.json 8 | 9 | 10 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/02-Linux-Capabilities/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [{"id":"f6f2187d.f17ca8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"8c2bb514.1d2198","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"influxdb","usetls":false,"tls":"","influxdbVersion":"2.0","url":"http://influxdb:8086","rejectUnauthorized":true},{"id":"9d41cfd6.5fe44","type":"inject","z":"f6f2187d.f17ca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":320,"y":400,"wires":[["10d047b2.ab2c38"]]},{"id":"10d047b2.ab2c38","type":"http request","z":"f6f2187d.f17ca8","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://dev1:5000","tls":"","persist":false,"proxy":"","authType":"","x":560,"y":400,"wires":[["686d18c1.2ec2d8","220b7260.eab46e"]]},{"id":"4c7a1fb7.c1aa9","type":"debug","z":"f6f2187d.f17ca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":790,"y":400,"wires":[]},{"id":"a536e7c7.4cb5a8","type":"influxdb out","z":"f6f2187d.f17ca8","influxdb":"8c2bb514.1d2198","name":"influxdb","measurement":"data","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"mtc","bucket":"mtcbucket","x":800,"y":500,"wires":[]},{"id":"220b7260.eab46e","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n [{\n temp: msg.payload.data.temp,\n },\n {\n device: msg.payload.data.device,\n name: msg.payload.data.container\n }],\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":500,"wires":[["a536e7c7.4cb5a8","4c7a1fb7.c1aa9"]]},{"id":"686d18c1.2ec2d8","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n{\n \"device\": msg.payload.data.device,\n \"container\": msg.payload.data.container,\n \"temperature\": msg.payload.data.temp\n}\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":580,"y":300,"wires":[["b56a527e.e41dc"]]},{"id":"b56a527e.e41dc","type":"http request","z":"f6f2187d.f17ca8","name":"postgrest","method":"POST","ret":"txt","paytoqs":"ignore","url":"http://postgrest:3000/temperature_data","tls":"","persist":false,"proxy":"","authType":"","x":790,"y":300,"wires":[["4c7a1fb7.c1aa9"]]}] -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/02-Linux-Capabilities/nodered/flows_cred.json: -------------------------------------------------------------------------------- 1 | {"8c2bb514.1d2198":{"token":"mtcderektoken"}} -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/02-Linux-Capabilities/postgres/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM postgres:13 2 | 3 | COPY schema.sql /docker-entrypoint-initdb.d/ -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/02-Linux-Capabilities/postgres/schema.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- PostgreSQL database dump 3 | -- 4 | 5 | -- Dumped from database version 13.2 (Debian 13.2-1.pgdg100+1) 6 | -- Dumped by pg_dump version 13.2 7 | 8 | -- Started on 2021-05-06 14:00:59 9 | 10 | SET statement_timeout = 0; 11 | SET lock_timeout = 0; 12 | SET idle_in_transaction_session_timeout = 0; 13 | SET client_encoding = 'UTF8'; 14 | SET standard_conforming_strings = on; 15 | SELECT pg_catalog.set_config('search_path', '', false); 16 | SET check_function_bodies = false; 17 | SET xmloption = content; 18 | SET client_min_messages = warning; 19 | SET row_security = off; 20 | 21 | SET default_tablespace = ''; 22 | 23 | SET default_table_access_method = heap; 24 | 25 | CREATE TABLE public.temperature_data ( 26 | id integer NOT NULL, 27 | device character varying, 28 | container character varying, 29 | temperature integer, 30 | created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL 31 | ); 32 | 33 | 34 | ALTER TABLE public.temperature_data ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY ( 35 | SEQUENCE NAME public.temp_data_id_seq 36 | START WITH 1 37 | INCREMENT BY 1 38 | NO MINVALUE 39 | NO MAXVALUE 40 | CACHE 1 41 | ); 42 | 43 | ALTER TABLE ONLY public.temperature_data 44 | ADD CONSTRAINT data_pkey PRIMARY KEY (id); 45 | 46 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/03-Connecting-to-VPN/dev1/.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # This file is a template, and might need editing before it works on your project. 2 | # Build a Docker image with CI/CD and push to the GitLab registry. 3 | # Docker-in-Docker documentation: https://docs.gitlab.com/ee/ci/docker/using_docker_build.html 4 | # 5 | # This template uses one generic job with conditional builds 6 | # for the default branch and all other (MR) branches. 7 | docker-build: 8 | # Use the official docker image. 9 | image: docker:latest 10 | stage: build 11 | services: 12 | - docker:dind 13 | before_script: 14 | - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY 15 | # Default branch leaves tag empty (= latest tag) 16 | # All other branches are tagged with the escaped branch name (commit ref slug) 17 | script: 18 | - | 19 | if [[ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]]; then 20 | tag="" 21 | echo "Running on default branch '$CI_DEFAULT_BRANCH': tag = 'latest'" 22 | else 23 | tag=":$CI_COMMIT_REF_SLUG" 24 | echo "Running on branch '$CI_COMMIT_BRANCH': tag = $tag" 25 | fi 26 | - docker build --pull -t "$CI_REGISTRY_IMAGE${tag}" . 27 | - docker push "$CI_REGISTRY_IMAGE${tag}" 28 | # Run this job in a branch where a Dockerfile exists 29 | rules: 30 | - if: $CI_COMMIT_BRANCH 31 | exists: 32 | - Dockerfile -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/03-Connecting-to-VPN/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/03-Connecting-to-VPN/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/03-Connecting-to-VPN/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/03-Connecting-to-VPN/dev1/gitinit.sh: -------------------------------------------------------------------------------- 1 | git init && 2 | git remote add origin https://gitlab.com/mtc-infra/$(echo ${PWD} | awk -F/ '{print $NF}').git && 3 | git add . && 4 | git commit -m "initial" && 5 | git push -u origin master -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/03-Connecting-to-VPN/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | # api: 4 | # container_name: dev1 5 | # image: registry.gitlab.com/mtc-infra/dev1:latest 6 | # networks: 7 | # - backend 8 | # volumes: 9 | # - type: volume 10 | # source: dev1-vol 11 | # target: /app 12 | # nodered: 13 | # container_name: nodered 14 | # build: ./nodered/ 15 | # networks: 16 | # - backend 17 | # ports: 18 | # - "1880:1880" 19 | # volumes: 20 | # - type: volume 21 | # source: nodered-vol 22 | # target: /data 23 | # environment: 24 | # - INFLUXDB_TOKEN=mtcderektoken 25 | # influxdb: 26 | # container_name: influxdb 27 | # image: registry.gitlab.com/mtc-infra/influxdb:latest 28 | # networks: 29 | # - backend 30 | # volumes: 31 | # - type: volume 32 | # source: influxdb-vol 33 | # target: /var/lib/influxdb2 34 | # environment: 35 | # - DOCKER_INFLUXDB_INIT_MODE=setup 36 | # - DOCKER_INFLUXDB_INIT_USERNAME=mtcderek 37 | # - DOCKER_INFLUXDB_INIT_PASSWORD=mtcderek 38 | # - DOCKER_INFLUXDB_INIT_ORG=mtc 39 | # - DOCKER_INFLUXDB_INIT_BUCKET=mtcbucket 40 | # - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=mtcderektoken 41 | # grafana: 42 | # container_name: grafana 43 | # image: registry.gitlab.com/mtc-infra/grafana:latest 44 | # environment: 45 | # - GF_SECURITY_ADMIN_USER=mtcderek 46 | # - GF_SECURITY_ADMIN_PASSWORD=mtcderek 47 | # - INFLUXDB_TOKEN=mtcderektoken 48 | # networks: 49 | # - frontend 50 | # - backend 51 | # - db 52 | # ports: 53 | # - "3000:3000" 54 | # volumes: 55 | # - type: volume 56 | # source: grafana-vol 57 | # target: /var/lib/grafana 58 | # postgres: 59 | # container_name: postgres 60 | # image: registry.gitlab.com/mtc-infra/postgres:latest 61 | # networks: 62 | # - db 63 | # volumes: 64 | # - type: volume 65 | # source: postgres-vol 66 | # target: /var/lib/postgresql/data/ 67 | # environment: 68 | # - POSTGRES_USER=mtcderek 69 | # - POSTGRES_PASSWORD=mtcderek 70 | # - POSTGRES_DB=mtcdb 71 | # postgrest: 72 | # container_name: postgrest 73 | # image: postgrest/postgrest 74 | # networks: 75 | # - backend 76 | # - db 77 | # environment: 78 | # - PGRST_DB_URI=postgres://mtcderek:mtcderek@postgres:5432/mtcdb 79 | # - PGRST_DB_ANON_ROLE=mtcderek 80 | wireguard: 81 | image: ghcr.io/linuxserver/wireguard 82 | container_name: wireguard 83 | cap_add: 84 | - NET_ADMIN 85 | - SYS_MODULE 86 | environment: 87 | - PUID=1000 88 | - PGID=1000 89 | - TZ=America/Chicago 90 | - PEERS=3 91 | volumes: 92 | - /home/ubuntu/environment/mtc-docker/Public/Lesson-Files/03-Connecting-to-VPN/01-VPN-Setup/wireguard/config:/config 93 | - /lib/modules:/lib/modules 94 | ports: 95 | - 51820:51820/udp 96 | volumes: 97 | dev1-vol: {} 98 | nodered-vol: {} 99 | influxdb-vol: {} 100 | grafana-vol: {} 101 | postgres-vol: {} 102 | networks: 103 | frontend: {} 104 | backend: {} 105 | db: {} -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/03-Connecting-to-VPN/grafana/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM grafana/grafana 2 | COPY datasource.yml /etc/grafana/provisioning/datasources 3 | COPY dashboards/ /etc/grafana/provisioning/dashboards 4 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/03-Connecting-to-VPN/grafana/dashboards/dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | providers: 3 | - name: 'Temperature' 4 | orgId: 1 5 | folder: 'new dashboards' 6 | type: file 7 | disableDeletion: false 8 | allowUiUpdates: false 9 | options: 10 | path: /etc/grafana/provisioning/dashboards 11 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/03-Connecting-to-VPN/grafana/datasource.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | datasources: 4 | - name: influxdb 5 | type: influxdb 6 | access: proxy 7 | url: http://influxdb:8086 8 | editable: true 9 | secureJsonData: 10 | token: $INFLUXDB_TOKEN 11 | jsonData: 12 | version: Flux 13 | organization: mtc 14 | defaultBucket: mtcbucket 15 | - name: postgres 16 | type: postgres 17 | access: proxy 18 | url: postgres:5432 19 | editable: true 20 | user: mtcderek 21 | database: mtcdb 22 | jsonData: 23 | postgresVersion: 1200 24 | sslmode: "disable" 25 | secureJsonData: 26 | password: mtcderek 27 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/03-Connecting-to-VPN/influxdb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM influxdb 2 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:8086 || nc -zv localhost 8086 || exit 1 -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/03-Connecting-to-VPN/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | RUN npm install node-red-contrib-influxdb 4 | 5 | COPY ./settings.js /data/settings.js 6 | COPY ./flows_cred.json /data/flows_cred.json 7 | COPY ./flows.json /data/flows.json 8 | 9 | 10 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/03-Connecting-to-VPN/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [{"id":"f6f2187d.f17ca8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"8c2bb514.1d2198","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"influxdb","usetls":false,"tls":"","influxdbVersion":"2.0","url":"http://influxdb:8086","rejectUnauthorized":true},{"id":"9d41cfd6.5fe44","type":"inject","z":"f6f2187d.f17ca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":320,"y":400,"wires":[["10d047b2.ab2c38"]]},{"id":"10d047b2.ab2c38","type":"http request","z":"f6f2187d.f17ca8","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://dev1:5000","tls":"","persist":false,"proxy":"","authType":"","x":560,"y":400,"wires":[["686d18c1.2ec2d8","220b7260.eab46e"]]},{"id":"4c7a1fb7.c1aa9","type":"debug","z":"f6f2187d.f17ca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":790,"y":400,"wires":[]},{"id":"a536e7c7.4cb5a8","type":"influxdb out","z":"f6f2187d.f17ca8","influxdb":"8c2bb514.1d2198","name":"influxdb","measurement":"data","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"mtc","bucket":"mtcbucket","x":800,"y":500,"wires":[]},{"id":"220b7260.eab46e","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n [{\n temp: msg.payload.data.temp,\n },\n {\n device: msg.payload.data.device,\n name: msg.payload.data.container\n }],\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":500,"wires":[["a536e7c7.4cb5a8","4c7a1fb7.c1aa9"]]},{"id":"686d18c1.2ec2d8","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n{\n \"device\": msg.payload.data.device,\n \"container\": msg.payload.data.container,\n \"temperature\": msg.payload.data.temp\n}\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":580,"y":300,"wires":[["b56a527e.e41dc"]]},{"id":"b56a527e.e41dc","type":"http request","z":"f6f2187d.f17ca8","name":"postgrest","method":"POST","ret":"txt","paytoqs":"ignore","url":"http://postgrest:3000/temperature_data","tls":"","persist":false,"proxy":"","authType":"","x":790,"y":300,"wires":[["4c7a1fb7.c1aa9"]]}] -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/03-Connecting-to-VPN/nodered/flows_cred.json: -------------------------------------------------------------------------------- 1 | {"8c2bb514.1d2198":{"token":"mtcderektoken"}} -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/03-Connecting-to-VPN/postgres/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM postgres 2 | 3 | COPY schema.sql /docker-entrypoint-initdb.d/ -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/03-Connecting-to-VPN/postgres/schema.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- PostgreSQL database dump 3 | -- 4 | 5 | -- Dumped from database version 13.2 (Debian 13.2-1.pgdg100+1) 6 | -- Dumped by pg_dump version 13.2 7 | 8 | -- Started on 2021-05-06 14:00:59 9 | 10 | SET statement_timeout = 0; 11 | SET lock_timeout = 0; 12 | SET idle_in_transaction_session_timeout = 0; 13 | SET client_encoding = 'UTF8'; 14 | SET standard_conforming_strings = on; 15 | SELECT pg_catalog.set_config('search_path', '', false); 16 | SET check_function_bodies = false; 17 | SET xmloption = content; 18 | SET client_min_messages = warning; 19 | SET row_security = off; 20 | 21 | SET default_tablespace = ''; 22 | 23 | SET default_table_access_method = heap; 24 | 25 | CREATE TABLE public.temperature_data ( 26 | id integer NOT NULL, 27 | device character varying, 28 | container character varying, 29 | temperature integer, 30 | created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL 31 | ); 32 | 33 | 34 | ALTER TABLE public.temperature_data ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY ( 35 | SEQUENCE NAME public.temp_data_id_seq 36 | START WITH 1 37 | INCREMENT BY 1 38 | NO MINVALUE 39 | NO MAXVALUE 40 | CACHE 1 41 | ); 42 | 43 | ALTER TABLE ONLY public.temperature_data 44 | ADD CONSTRAINT data_pkey PRIMARY KEY (id); 45 | 46 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/04-service_mode/dev1/.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # This file is a template, and might need editing before it works on your project. 2 | # Build a Docker image with CI/CD and push to the GitLab registry. 3 | # Docker-in-Docker documentation: https://docs.gitlab.com/ee/ci/docker/using_docker_build.html 4 | # 5 | # This template uses one generic job with conditional builds 6 | # for the default branch and all other (MR) branches. 7 | docker-build: 8 | # Use the official docker image. 9 | image: docker:latest 10 | stage: build 11 | services: 12 | - docker:dind 13 | before_script: 14 | - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY 15 | # Default branch leaves tag empty (= latest tag) 16 | # All other branches are tagged with the escaped branch name (commit ref slug) 17 | script: 18 | - | 19 | if [[ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]]; then 20 | tag="" 21 | echo "Running on default branch '$CI_DEFAULT_BRANCH': tag = 'latest'" 22 | else 23 | tag=":$CI_COMMIT_REF_SLUG" 24 | echo "Running on branch '$CI_COMMIT_BRANCH': tag = $tag" 25 | fi 26 | - docker build --pull -t "$CI_REGISTRY_IMAGE${tag}" . 27 | - docker push "$CI_REGISTRY_IMAGE${tag}" 28 | # Run this job in a branch where a Dockerfile exists 29 | rules: 30 | - if: $CI_COMMIT_BRANCH 31 | exists: 32 | - Dockerfile -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/04-service_mode/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/04-service_mode/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/04-service_mode/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/04-service_mode/dev1/gitinit.sh: -------------------------------------------------------------------------------- 1 | git init && 2 | git remote add origin https://gitlab.com/mtc-infra/$(echo ${PWD} | awk -F/ '{print $NF}').git && 3 | git add . && 4 | git commit -m "initial" && 5 | git push -u origin master -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/04-service_mode/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | # api: 4 | # container_name: dev1 5 | # image: registry.gitlab.com/mtc-infra/dev1:latest 6 | # networks: 7 | # - backend 8 | # volumes: 9 | # - type: volume 10 | # source: dev1-vol 11 | # target: /app 12 | # nodered: 13 | # container_name: nodered 14 | # build: ./nodered/ 15 | # networks: 16 | # - backend 17 | # ports: 18 | # - "1880:1880" 19 | # volumes: 20 | # - type: volume 21 | # source: nodered-vol 22 | # target: /data 23 | # environment: 24 | # - INFLUXDB_TOKEN=mtcderektoken 25 | # influxdb: 26 | # container_name: influxdb 27 | # image: registry.gitlab.com/mtc-infra/influxdb:latest 28 | # networks: 29 | # - backend 30 | # volumes: 31 | # - type: volume 32 | # source: influxdb-vol 33 | # target: /var/lib/influxdb2 34 | # environment: 35 | # - DOCKER_INFLUXDB_INIT_MODE=setup 36 | # - DOCKER_INFLUXDB_INIT_USERNAME=mtcderek 37 | # - DOCKER_INFLUXDB_INIT_PASSWORD=mtcderek 38 | # - DOCKER_INFLUXDB_INIT_ORG=mtc 39 | # - DOCKER_INFLUXDB_INIT_BUCKET=mtcbucket 40 | # - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=mtcderektoken 41 | grafana: 42 | container_name: grafana 43 | image: registry.gitlab.com/mtc-infra/grafana:latest 44 | environment: 45 | - GF_SECURITY_ADMIN_USER=mtcderek 46 | - GF_SECURITY_ADMIN_PASSWORD=mtcderek 47 | - INFLUXDB_TOKEN=mtcderektoken 48 | # networks: 49 | # - frontend 50 | # - backend 51 | # - db 52 | # ports: 53 | # - "3000:3000" 54 | network_mode: service:wireguard 55 | volumes: 56 | - type: volume 57 | source: grafana-vol 58 | target: /var/lib/grafana 59 | # postgres: 60 | # container_name: postgres 61 | # image: registry.gitlab.com/mtc-infra/postgres:latest 62 | # networks: 63 | # - db 64 | # volumes: 65 | # - type: volume 66 | # source: postgres-vol 67 | # target: /var/lib/postgresql/data/ 68 | # environment: 69 | # - POSTGRES_USER=mtcderek 70 | # - POSTGRES_PASSWORD=mtcderek 71 | # - POSTGRES_DB=mtcdb 72 | # postgrest: 73 | # container_name: postgrest 74 | # image: postgrest/postgrest 75 | # networks: 76 | # - backend 77 | # - db 78 | # environment: 79 | # - PGRST_DB_URI=postgres://mtcderek:mtcderek@postgres:5432/mtcdb 80 | # - PGRST_DB_ANON_ROLE=mtcderek 81 | wireguard: 82 | image: ghcr.io/linuxserver/wireguard 83 | container_name: wireguard 84 | cap_add: 85 | - NET_ADMIN 86 | - SYS_MODULE 87 | environment: 88 | - PUID=1000 89 | - PGID=1000 90 | - TZ=America/Chicago 91 | - PEERS=3 92 | volumes: 93 | - /home/ubuntu/environment/mtc-docker/Public/Lesson-Files/04-Docker-Admin/01-VPN-Setup/wireguard/config:/config 94 | - /lib/modules:/lib/modules 95 | ports: 96 | - 51820:51820/udp 97 | # networks: 98 | # - frontend 99 | # - backend 100 | # - db 101 | volumes: 102 | dev1-vol: {} 103 | nodered-vol: {} 104 | influxdb-vol: {} 105 | grafana-vol: {} 106 | postgres-vol: {} 107 | networks: 108 | frontend: {} 109 | backend: {} 110 | db: {} -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/04-service_mode/grafana/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM grafana/grafana 2 | COPY datasource.yml /etc/grafana/provisioning/datasources 3 | COPY dashboards/ /etc/grafana/provisioning/dashboards 4 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/04-service_mode/grafana/dashboards/dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | providers: 3 | - name: 'Temperature' 4 | orgId: 1 5 | folder: 'new dashboards' 6 | type: file 7 | disableDeletion: false 8 | allowUiUpdates: false 9 | options: 10 | path: /etc/grafana/provisioning/dashboards 11 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/04-service_mode/grafana/datasource.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | datasources: 4 | - name: influxdb 5 | type: influxdb 6 | access: proxy 7 | url: http://influxdb:8086 8 | editable: true 9 | secureJsonData: 10 | token: $INFLUXDB_TOKEN 11 | jsonData: 12 | version: Flux 13 | organization: mtc 14 | defaultBucket: mtcbucket 15 | - name: postgres 16 | type: postgres 17 | access: proxy 18 | url: postgres:5432 19 | editable: true 20 | user: mtcderek 21 | database: mtcdb 22 | jsonData: 23 | postgresVersion: 1200 24 | sslmode: "disable" 25 | secureJsonData: 26 | password: mtcderek 27 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/04-service_mode/influxdb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM influxdb 2 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:8086 || nc -zv localhost 8086 || exit 1 -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/04-service_mode/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | RUN npm install node-red-contrib-influxdb 4 | 5 | COPY ./settings.js /data/settings.js 6 | COPY ./flows_cred.json /data/flows_cred.json 7 | COPY ./flows.json /data/flows.json 8 | 9 | 10 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/04-service_mode/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [{"id":"f6f2187d.f17ca8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"8c2bb514.1d2198","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"influxdb","usetls":false,"tls":"","influxdbVersion":"2.0","url":"http://influxdb:8086","rejectUnauthorized":true},{"id":"9d41cfd6.5fe44","type":"inject","z":"f6f2187d.f17ca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":320,"y":400,"wires":[["10d047b2.ab2c38"]]},{"id":"10d047b2.ab2c38","type":"http request","z":"f6f2187d.f17ca8","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://dev1:5000","tls":"","persist":false,"proxy":"","authType":"","x":560,"y":400,"wires":[["686d18c1.2ec2d8","220b7260.eab46e"]]},{"id":"4c7a1fb7.c1aa9","type":"debug","z":"f6f2187d.f17ca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":790,"y":400,"wires":[]},{"id":"a536e7c7.4cb5a8","type":"influxdb out","z":"f6f2187d.f17ca8","influxdb":"8c2bb514.1d2198","name":"influxdb","measurement":"data","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"mtc","bucket":"mtcbucket","x":800,"y":500,"wires":[]},{"id":"220b7260.eab46e","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n [{\n temp: msg.payload.data.temp,\n },\n {\n device: msg.payload.data.device,\n name: msg.payload.data.container\n }],\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":500,"wires":[["a536e7c7.4cb5a8","4c7a1fb7.c1aa9"]]},{"id":"686d18c1.2ec2d8","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n{\n \"device\": msg.payload.data.device,\n \"container\": msg.payload.data.container,\n \"temperature\": msg.payload.data.temp\n}\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":580,"y":300,"wires":[["b56a527e.e41dc"]]},{"id":"b56a527e.e41dc","type":"http request","z":"f6f2187d.f17ca8","name":"postgrest","method":"POST","ret":"txt","paytoqs":"ignore","url":"http://postgrest:3000/temperature_data","tls":"","persist":false,"proxy":"","authType":"","x":790,"y":300,"wires":[["4c7a1fb7.c1aa9"]]}] -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/04-service_mode/nodered/flows_cred.json: -------------------------------------------------------------------------------- 1 | {"8c2bb514.1d2198":{"token":"mtcderektoken"}} -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/04-service_mode/postgres/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM postgres 2 | 3 | COPY schema.sql /docker-entrypoint-initdb.d/ -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/04-service_mode/postgres/schema.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- PostgreSQL database dump 3 | -- 4 | 5 | -- Dumped from database version 13.2 (Debian 13.2-1.pgdg100+1) 6 | -- Dumped by pg_dump version 13.2 7 | 8 | -- Started on 2021-05-06 14:00:59 9 | 10 | SET statement_timeout = 0; 11 | SET lock_timeout = 0; 12 | SET idle_in_transaction_session_timeout = 0; 13 | SET client_encoding = 'UTF8'; 14 | SET standard_conforming_strings = on; 15 | SELECT pg_catalog.set_config('search_path', '', false); 16 | SET check_function_bodies = false; 17 | SET xmloption = content; 18 | SET client_min_messages = warning; 19 | SET row_security = off; 20 | 21 | SET default_tablespace = ''; 22 | 23 | SET default_table_access_method = heap; 24 | 25 | CREATE TABLE public.temperature_data ( 26 | id integer NOT NULL, 27 | device character varying, 28 | container character varying, 29 | temperature integer, 30 | created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL 31 | ); 32 | 33 | 34 | ALTER TABLE public.temperature_data ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY ( 35 | SEQUENCE NAME public.temp_data_id_seq 36 | START WITH 1 37 | INCREMENT BY 1 38 | NO MINVALUE 39 | NO MAXVALUE 40 | CACHE 1 41 | ); 42 | 43 | ALTER TABLE ONLY public.temperature_data 44 | ADD CONSTRAINT data_pkey PRIMARY KEY (id); 45 | 46 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/05-Rest-of-Stack/dev1/.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # This file is a template, and might need editing before it works on your project. 2 | # Build a Docker image with CI/CD and push to the GitLab registry. 3 | # Docker-in-Docker documentation: https://docs.gitlab.com/ee/ci/docker/using_docker_build.html 4 | # 5 | # This template uses one generic job with conditional builds 6 | # for the default branch and all other (MR) branches. 7 | docker-build: 8 | # Use the official docker image. 9 | image: docker:latest 10 | stage: build 11 | services: 12 | - docker:dind 13 | before_script: 14 | - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY 15 | # Default branch leaves tag empty (= latest tag) 16 | # All other branches are tagged with the escaped branch name (commit ref slug) 17 | script: 18 | - | 19 | if [[ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]]; then 20 | tag="" 21 | echo "Running on default branch '$CI_DEFAULT_BRANCH': tag = 'latest'" 22 | else 23 | tag=":$CI_COMMIT_REF_SLUG" 24 | echo "Running on branch '$CI_COMMIT_BRANCH': tag = $tag" 25 | fi 26 | - docker build --pull -t "$CI_REGISTRY_IMAGE${tag}" . 27 | - docker push "$CI_REGISTRY_IMAGE${tag}" 28 | # Run this job in a branch where a Dockerfile exists 29 | rules: 30 | - if: $CI_COMMIT_BRANCH 31 | exists: 32 | - Dockerfile -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/05-Rest-of-Stack/dev1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | 3 | COPY ./app/requirements.txt /app/requirements.txt 4 | 5 | WORKDIR /app 6 | 7 | RUN pip install -r requirements.txt 8 | 9 | ENV DEVICE="dev1" 10 | 11 | COPY ./app/ /app 12 | 13 | ENTRYPOINT [ "python" ] 14 | 15 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:5000 || nc -zv localhost 5000 || exit 1 16 | 17 | CMD [ "app.py" ] 18 | 19 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/05-Rest-of-Stack/dev1/app/app.py: -------------------------------------------------------------------------------- 1 | # flask_web/app.py 2 | 3 | from flask import Flask, jsonify, request 4 | import random 5 | import os 6 | 7 | app = Flask(__name__) 8 | app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False 9 | 10 | @app.route('/', methods=['GET']) 11 | def hello_world(): 12 | return jsonify({"data": {"container" : os.getenv('HOSTNAME') , "device" : os.getenv('DEVICE'), "temp" : random.randrange(-10, 20, 1)}}) 13 | 14 | 15 | if __name__ == '__main__': 16 | app.run(debug=True, host='0.0.0.0') -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/05-Rest-of-Stack/dev1/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/05-Rest-of-Stack/dev1/gitinit.sh: -------------------------------------------------------------------------------- 1 | git init && 2 | git remote add origin https://gitlab.com/mtc-infra/$(echo ${PWD} | awk -F/ '{print $NF}').git && 3 | git add . && 4 | git commit -m "initial" && 5 | git push -u origin master -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/05-Rest-of-Stack/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | api: 4 | container_name: dev1 5 | image: registry.gitlab.com/mtc-infra/dev1:latest 6 | networks: 7 | - backend 8 | volumes: 9 | - type: volume 10 | source: dev1-vol 11 | target: /app 12 | nodered: 13 | container_name: nodered 14 | build: ./nodered/ 15 | networks: 16 | - backend 17 | ports: 18 | - "1880:1880" 19 | volumes: 20 | - type: volume 21 | source: nodered-vol 22 | target: /data 23 | environment: 24 | - INFLUXDB_TOKEN=mtcderektoken 25 | influxdb: 26 | container_name: influxdb 27 | image: registry.gitlab.com/mtc-infra/influxdb:latest 28 | networks: 29 | - backend 30 | volumes: 31 | - type: volume 32 | source: influxdb-vol 33 | target: /var/lib/influxdb2 34 | environment: 35 | - DOCKER_INFLUXDB_INIT_MODE=setup 36 | - DOCKER_INFLUXDB_INIT_USERNAME=mtcderek 37 | - DOCKER_INFLUXDB_INIT_PASSWORD=mtcderek 38 | - DOCKER_INFLUXDB_INIT_ORG=mtc 39 | - DOCKER_INFLUXDB_INIT_BUCKET=mtcbucket 40 | - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=mtcderektoken 41 | grafana: 42 | container_name: grafana 43 | image: registry.gitlab.com/mtc-infra/grafana:latest 44 | environment: 45 | - GF_SECURITY_ADMIN_USER=mtcderek 46 | - GF_SECURITY_ADMIN_PASSWORD=mtcderek 47 | - INFLUXDB_TOKEN=mtcderektoken 48 | networks: 49 | - frontend 50 | - backend 51 | - db 52 | ports: 53 | - "3000:3000" 54 | volumes: 55 | - type: volume 56 | source: grafana-vol 57 | target: /var/lib/grafana 58 | postgres: 59 | container_name: postgres 60 | image: registry.gitlab.com/mtc-infra/postgres:latest 61 | networks: 62 | - db 63 | volumes: 64 | - type: volume 65 | source: postgres-vol 66 | target: /var/lib/postgresql/data/ 67 | environment: 68 | - POSTGRES_USER=mtcderek 69 | - POSTGRES_PASSWORD=mtcderek 70 | - POSTGRES_DB=mtcdb 71 | postgrest: 72 | container_name: postgrest 73 | image: postgrest/postgrest 74 | networks: 75 | - backend 76 | - db 77 | environment: 78 | - PGRST_DB_URI=postgres://mtcderek:mtcderek@postgres:5432/mtcdb 79 | - PGRST_DB_ANON_ROLE=mtcderek 80 | wireguard: 81 | image: ghcr.io/linuxserver/wireguard 82 | container_name: wireguard 83 | cap_add: 84 | - NET_ADMIN 85 | - SYS_MODULE 86 | environment: 87 | - PUID=1000 88 | - PGID=1000 89 | - TZ=America/Chicago 90 | - PEERS=3 91 | volumes: 92 | - /home/ubuntu/environment/mtc-docker/Public/Lesson-Files/04-Docker-Admin/05-Rest-of-Stack/wireguard/config:/config 93 | - /lib/modules:/lib/modules 94 | ports: 95 | - 51820:51820/udp 96 | volumes: 97 | dev1-vol: {} 98 | nodered-vol: {} 99 | influxdb-vol: {} 100 | grafana-vol: {} 101 | postgres-vol: {} 102 | networks: 103 | frontend: {} 104 | backend: {} 105 | db: {} -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/05-Rest-of-Stack/grafana/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM grafana/grafana 2 | COPY datasource.yml /etc/grafana/provisioning/datasources 3 | COPY dashboards/ /etc/grafana/provisioning/dashboards 4 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/05-Rest-of-Stack/grafana/dashboards/dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | providers: 3 | - name: 'Temperature' 4 | orgId: 1 5 | folder: 'new dashboards' 6 | type: file 7 | disableDeletion: false 8 | allowUiUpdates: false 9 | options: 10 | path: /etc/grafana/provisioning/dashboards 11 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/05-Rest-of-Stack/grafana/datasource.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | datasources: 4 | - name: influxdb 5 | type: influxdb 6 | access: proxy 7 | url: http://influxdb:8086 8 | editable: true 9 | secureJsonData: 10 | token: $INFLUXDB_TOKEN 11 | jsonData: 12 | version: Flux 13 | organization: mtc 14 | defaultBucket: mtcbucket 15 | - name: postgres 16 | type: postgres 17 | access: proxy 18 | url: postgres:5432 19 | editable: true 20 | user: mtcderek 21 | database: mtcdb 22 | jsonData: 23 | postgresVersion: 1200 24 | sslmode: "disable" 25 | secureJsonData: 26 | password: mtcderek 27 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/05-Rest-of-Stack/influxdb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM influxdb 2 | HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost:8086 || nc -zv localhost 8086 || exit 1 -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/05-Rest-of-Stack/nodered/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nodered/node-red 2 | 3 | RUN npm install node-red-contrib-influxdb 4 | 5 | COPY ./settings.js /data/settings.js 6 | COPY ./flows_cred.json /data/flows_cred.json 7 | COPY ./flows.json /data/flows.json 8 | 9 | 10 | -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/05-Rest-of-Stack/nodered/flows.json: -------------------------------------------------------------------------------- 1 | [{"id":"f6f2187d.f17ca8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"8c2bb514.1d2198","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"influxdb","usetls":false,"tls":"","influxdbVersion":"2.0","url":"http://influxdb:8086","rejectUnauthorized":true},{"id":"9d41cfd6.5fe44","type":"inject","z":"f6f2187d.f17ca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":320,"y":400,"wires":[["10d047b2.ab2c38"]]},{"id":"10d047b2.ab2c38","type":"http request","z":"f6f2187d.f17ca8","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://dev1:5000","tls":"","persist":false,"proxy":"","authType":"","x":560,"y":400,"wires":[["686d18c1.2ec2d8","220b7260.eab46e"]]},{"id":"4c7a1fb7.c1aa9","type":"debug","z":"f6f2187d.f17ca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":790,"y":400,"wires":[]},{"id":"a536e7c7.4cb5a8","type":"influxdb out","z":"f6f2187d.f17ca8","influxdb":"8c2bb514.1d2198","name":"influxdb","measurement":"data","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"mtc","bucket":"mtcbucket","x":800,"y":500,"wires":[]},{"id":"220b7260.eab46e","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n [{\n temp: msg.payload.data.temp,\n },\n {\n device: msg.payload.data.device,\n name: msg.payload.data.container\n }],\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":500,"wires":[["a536e7c7.4cb5a8","4c7a1fb7.c1aa9"]]},{"id":"686d18c1.2ec2d8","type":"function","z":"f6f2187d.f17ca8","name":"","func":"msg.payload = [\n{\n \"device\": msg.payload.data.device,\n \"container\": msg.payload.data.container,\n \"temperature\": msg.payload.data.temp\n}\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":580,"y":300,"wires":[["b56a527e.e41dc"]]},{"id":"b56a527e.e41dc","type":"http request","z":"f6f2187d.f17ca8","name":"postgrest","method":"POST","ret":"txt","paytoqs":"ignore","url":"http://postgrest:3000/temperature_data","tls":"","persist":false,"proxy":"","authType":"","x":790,"y":300,"wires":[["4c7a1fb7.c1aa9"]]}] -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/05-Rest-of-Stack/nodered/flows_cred.json: -------------------------------------------------------------------------------- 1 | {"8c2bb514.1d2198":{"token":"mtcderektoken"}} -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/05-Rest-of-Stack/postgres/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM postgres:13 2 | 3 | COPY schema.sql /docker-entrypoint-initdb.d/ -------------------------------------------------------------------------------- /Lesson-Files/04-Docker-Admin/05-Rest-of-Stack/postgres/schema.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- PostgreSQL database dump 3 | -- 4 | 5 | -- Dumped from database version 13.2 (Debian 13.2-1.pgdg100+1) 6 | -- Dumped by pg_dump version 13.2 7 | 8 | -- Started on 2021-05-06 14:00:59 9 | 10 | SET statement_timeout = 0; 11 | SET lock_timeout = 0; 12 | SET idle_in_transaction_session_timeout = 0; 13 | SET client_encoding = 'UTF8'; 14 | SET standard_conforming_strings = on; 15 | SELECT pg_catalog.set_config('search_path', '', false); 16 | SET check_function_bodies = false; 17 | SET xmloption = content; 18 | SET client_min_messages = warning; 19 | SET row_security = off; 20 | 21 | SET default_tablespace = ''; 22 | 23 | SET default_table_access_method = heap; 24 | 25 | CREATE TABLE public.temperature_data ( 26 | id integer NOT NULL, 27 | device character varying, 28 | container character varying, 29 | temperature integer, 30 | created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL 31 | ); 32 | 33 | 34 | ALTER TABLE public.temperature_data ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY ( 35 | SEQUENCE NAME public.temp_data_id_seq 36 | START WITH 1 37 | INCREMENT BY 1 38 | NO MINVALUE 39 | NO MAXVALUE 40 | CACHE 1 41 | ); 42 | 43 | ALTER TABLE ONLY public.temperature_data 44 | ADD CONSTRAINT data_pkey PRIMARY KEY (id); 45 | 46 | --------------------------------------------------------------------------------