From 5ba669e963814fe0f7409543334f25bef627b5e2 Mon Sep 17 00:00:00 2001 From: Florian Dahlitz Date: Mon, 1 Apr 2019 22:09:39 +0200 Subject: [PATCH 01/28] feat(docker-compose): update docker-compose.yml to version 3 --- docker-compose.yml | 87 +++++++++++++++++++++++++--------------------- production.yml | 80 ++++++++++++++++++++++-------------------- 2 files changed, 90 insertions(+), 77 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 35238e5..85bfdbc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,43 +1,50 @@ -web: - restart: always - build: ./web - expose: - - "8000" - links: - - postgres:postgres - - redis:redis - volumes: - - /usr/src/app - - /usr/src/app/static - env_file: .env - environment: - DEBUG: 'true' - command: /usr/local/bin/gunicorn docker_django.wsgi:application -w 2 -b :8000 +version: '3' -nginx: - restart: always - build: ./nginx/ - ports: - - "80:80" - volumes: - - /www/static - volumes_from: - - web - links: - - web:web +services: + web: + restart: always + build: ./web + expose: + - "8000" + links: + - postgres:postgres + - redis:redis + volumes: + - web-django:/usr/src/app + - web-static:/usr/src/app/static + env_file: .env + environment: + DEBUG: 'true' + command: /usr/local/bin/gunicorn docker_django.wsgi:application -w 2 -b :8000 -postgres: - restart: always - image: postgres:latest - ports: - - "5432:5432" - volumes: - - pgdata:/var/lib/postgresql/data/ + nginx: + restart: always + build: ./nginx/ + ports: + - "80:80" + volumes: + - web-static:/www/static + links: + - web:web -redis: - restart: always - image: redis:latest - ports: - - "6379:6379" - volumes: - - redisdata:/data \ No newline at end of file + postgres: + restart: always + image: postgres:latest + ports: + - "5432:5432" + volumes: + - pgdata:/var/lib/postgresql/data/ + + redis: + restart: always + image: redis:latest + ports: + - "6379:6379" + volumes: + - redisdata:/data + +volumes: + web-django: + web-static: + pgdata: + redisdata: diff --git a/production.yml b/production.yml index 6c1366e..c6f5755 100644 --- a/production.yml +++ b/production.yml @@ -1,40 +1,46 @@ -web: - restart: always - build: ./web - expose: - - "8000" - links: - - postgres:postgres - - redis:redis - volumes: - - /usr/src/app/static - env_file: .env - command: /usr/local/bin/gunicorn docker_django.wsgi:application -w 2 -b :8000 +version: '3' -nginx: - restart: always - build: ./nginx/ - ports: - - "80:80" - volumes: - - /www/static - volumes_from: - - web - links: - - web:web +services: + web: + restart: always + build: ./web + expose: + - "8000" + links: + - postgres:postgres + - redis:redis + volumes: + - web-static:/usr/src/app/static + env_file: .env + command: /usr/local/bin/gunicorn docker_django.wsgi:application -w 2 -b :8000 -postgres: - restart: always - image: postgres:latest - ports: - - "5432" - volumes: - - pgdata:/var/lib/postgresql/data/ + nginx: + restart: always + build: ./nginx/ + ports: + - "80:80" + volumes: + - web-static:/www/static + links: + - web:web -redis: - restart: always - image: redis:latest - ports: - - "6379" - volumes: - - redisdata:/data + postgres: + restart: always + image: postgres:latest + ports: + - "5432" + volumes: + - pgdata:/var/lib/postgresql/data/ + + redis: + restart: always + image: redis:latest + ports: + - "6379" + volumes: + - redisdata:/data + +volumes: + web-static: + pgdata: + redisdata: From d2ceb8d80413fe1c25a3dc79bb28b0c73e48c109 Mon Sep 17 00:00:00 2001 From: Florian Dahlitz Date: Mon, 1 Apr 2019 22:11:14 +0200 Subject: [PATCH 02/28] refactoring(nginx): use COPY instead of ADD as it is more clear --- nginx/Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nginx/Dockerfile b/nginx/Dockerfile index 2a99696..fa05639 100644 --- a/nginx/Dockerfile +++ b/nginx/Dockerfile @@ -1,3 +1,5 @@ FROM tutum/nginx + RUN rm /etc/nginx/sites-enabled/default -ADD sites-enabled/ /etc/nginx/sites-enabled + +COPY sites-enabled/ /etc/nginx/sites-enabled From a6cbea50b9710d261e939594d17b7859189baadf Mon Sep 17 00:00:00 2001 From: Florian Dahlitz Date: Mon, 1 Apr 2019 22:40:53 +0200 Subject: [PATCH 03/28] feat(web): update to Python 3.7 and latest package versions --- web/Dockerfile | 9 ++++++++- web/docker_django/apps/todo/urls.py | 4 ++-- web/docker_django/urls.py | 6 +++--- web/requirements.txt | 8 ++++---- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/web/Dockerfile b/web/Dockerfile index 2688a8b..dffd83b 100644 --- a/web/Dockerfile +++ b/web/Dockerfile @@ -1 +1,8 @@ -FROM python:3.5-onbuild +FROM python:3.7-slim + +RUN python -m pip install --upgrade pip + +COPY requirements.txt requirements.txt +RUN python -m pip install -r requirements.txt + +COPY . . diff --git a/web/docker_django/apps/todo/urls.py b/web/docker_django/apps/todo/urls.py index 42147e6..68083db 100644 --- a/web/docker_django/apps/todo/urls.py +++ b/web/docker_django/apps/todo/urls.py @@ -1,7 +1,7 @@ -from django.conf.urls import url +from django.urls import re_path from . import views urlpatterns = [ - url(r'^$', views.home, name='home'), + re_path(r'^$', views.home, name='home'), ] diff --git a/web/docker_django/urls.py b/web/docker_django/urls.py index 728b4fa..6702f18 100644 --- a/web/docker_django/urls.py +++ b/web/docker_django/urls.py @@ -1,7 +1,7 @@ -from django.conf.urls import include, url +from django.urls import include, re_path from django.contrib import admin urlpatterns = [ - url(r'^admin/', include(admin.site.urls)), - url(r'^', include('docker_django.apps.todo.urls')), + re_path(r'^admin/', admin.site.urls), + re_path(r'^', include('docker_django.apps.todo.urls')), ] diff --git a/web/requirements.txt b/web/requirements.txt index 00f3f4e..004b0d3 100644 --- a/web/requirements.txt +++ b/web/requirements.txt @@ -1,4 +1,4 @@ -Django==1.8.1 -gunicorn==19.3.0 -psycopg2==2.6 -redis==2.10.3 +Django==2.1.7 +gunicorn==19.9.0 +psycopg2==2.7.7 +redis==3.2.1 From d556ed9ec76a793bbcee0a34efce8247300d56eb Mon Sep 17 00:00:00 2001 From: Florian Dahlitz Date: Mon, 1 Apr 2019 22:57:20 +0200 Subject: [PATCH 04/28] docs(chore): update docker version --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 869a58a..a02831d 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,10 @@ Featuring: -- Docker v1.10.3 -- Docker Compose v1.6.2 -- Docker Machine v0.6.0 -- Python 3.5 +- Docker v18.09.2 +- Docker Compose v1.23.2 +- Docker Machine v0.16.1 +- Python 3.7.3 Blog post -> https://realpython.com/blog/python/django-development-with-docker-compose-and-machine/ From e1f2ce46cdcd7140066d6629626aacae05938c28 Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Thu, 4 Jul 2019 15:18:29 +0300 Subject: [PATCH 05/28] add mysql-connector to requirements --- web/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/requirements.txt b/web/requirements.txt index 004b0d3..f71dc19 100644 --- a/web/requirements.txt +++ b/web/requirements.txt @@ -1,4 +1,4 @@ Django==2.1.7 gunicorn==19.9.0 -psycopg2==2.7.7 redis==3.2.1 +mysql-connector-python==8.0.16 From cb53c40d832fcce3ee5c7f88681c90c76ba401b8 Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Thu, 4 Jul 2019 15:19:10 +0300 Subject: [PATCH 06/28] Set workdir in web Dockerfile --- web/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web/Dockerfile b/web/Dockerfile index dffd83b..b1c56f7 100644 --- a/web/Dockerfile +++ b/web/Dockerfile @@ -2,7 +2,9 @@ FROM python:3.7-slim RUN python -m pip install --upgrade pip +WORKDIR /usr/src/app COPY requirements.txt requirements.txt + RUN python -m pip install -r requirements.txt COPY . . From 8c4a1ca5c0ac406a6534715f032b3f5ebdb36454 Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Thu, 4 Jul 2019 15:20:25 +0300 Subject: [PATCH 07/28] Change db engine in settings to mysql --- web/docker_django/settings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/docker_django/settings.py b/web/docker_django/settings.py index 19ec07f..e6f1409 100644 --- a/web/docker_django/settings.py +++ b/web/docker_django/settings.py @@ -85,11 +85,11 @@ DATABASES = { 'default': { - 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'ENGINE': 'mysql.connector.django', 'NAME': os.environ['DB_NAME'], 'USER': os.environ['DB_USER'], 'PASSWORD': os.environ['DB_PASS'], - 'HOST': os.environ['DB_SERVICE'], + 'HOST': os.environ['DB_HOST'], 'PORT': os.environ['DB_PORT'] } } From 9e02d947b7259ee99da87cc701f7b743f5749d2b Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Thu, 4 Jul 2019 15:21:38 +0300 Subject: [PATCH 08/28] update alias directory in nginx --- nginx/sites-enabled/django_project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nginx/sites-enabled/django_project b/nginx/sites-enabled/django_project index 1285c6c..eabffec 100644 --- a/nginx/sites-enabled/django_project +++ b/nginx/sites-enabled/django_project @@ -5,7 +5,7 @@ server { charset utf-8; location /static { - alias /usr/src/app/static; + alias /www/static; } location / { From 60869ffb5d3be8ad932f754973f081dcf2030004 Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Thu, 4 Jul 2019 15:23:37 +0300 Subject: [PATCH 09/28] replace postgres with mysql --- docker-compose.yml | 50 +++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 85bfdbc..a9f397c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,50 +1,50 @@ -version: '3' +version: '2.1' services: web: restart: always build: ./web - expose: - - "8000" - links: - - postgres:postgres - - redis:redis + ports: + - "${WEB_PORT}:8000" volumes: - - web-django:/usr/src/app - - web-static:/usr/src/app/static - env_file: .env + - ./web:/usr/src/app + env_file: my.env environment: DEBUG: 'true' - command: /usr/local/bin/gunicorn docker_django.wsgi:application -w 2 -b :8000 + command: bash -c "python manage.py makemigrations todo && python manage.py migrate && gunicorn docker_django.wsgi:application --reload -w 2 -b :8000" nginx: restart: always - build: ./nginx/ + build: ./nginx ports: - - "80:80" + - "${NGINX_PORT}:80" volumes: - - web-static:/www/static + - ./web/static:/www/static + - ./nginx/sites-enabled:/etc/nginx/sites-enabled links: - web:web - postgres: - restart: always - image: postgres:latest - ports: - - "5432:5432" - volumes: - - pgdata:/var/lib/postgresql/data/ - redis: restart: always image: redis:latest ports: - - "6379:6379" + - "${REDIS_PORT}:6379" volumes: - redisdata:/data + + mysql-db: + image: mysql:5.7 + environment: + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} + MYSQL_DATABASE: ${MYSQL_DATABASE} + MYSQL_USER: ${MYSQL_USER} + MYSQL_PASSWORD: ${MYSQL_PASSWORD} + ports: + - "${MYSQL_PORT}:3306" + volumes: + - mysql-vol:/var/lib/mysql + - ./mysql/:/docker-entrypoint-initdb.d/ volumes: - web-django: - web-static: - pgdata: + mysql-vol: redisdata: From 6a83e084cb53a26ded20c4761e2454e49a366c9b Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Thu, 4 Jul 2019 15:25:10 +0300 Subject: [PATCH 10/28] update env variables --- .env | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/.env b/.env index a2d402c..f9d13bb 100644 --- a/.env +++ b/.env @@ -1,9 +1,19 @@ -# Add Environment Variables +# django/web environment variables +SECRET_KEY=5(15ds+i2+%ik6z&!yer+ga9m=e%jcqiz_5wszg)r-z!2--b2d +DB_NAME=todo +DB_USER=todo +DB_PASS=pass +DB_HOST=mysql-db +DB_PORT=3306 +# mysql database variables +MYSQL_ROOT_PASSWORD=password +MYSQL_DATABASE=todo +MYSQL_USER=todo +MYSQL_PASSWORD=pass -SECRET_KEY=5(15ds+i2+%ik6z&!yer+ga9m=e%jcqiz_5wszg)r-z!2--b2d -DB_NAME=postgres -DB_USER=postgres -DB_PASS=postgres -DB_SERVICE=postgres -DB_PORT=5432 \ No newline at end of file +# expose ports on host +WEB_PORT=8000 +NGINX_PORT=80 +REDIS_PORT=6379 +MYSQL_PORT=3306 From 1fdea2a4b811d8ddb7aa6af0c6ecd557c44c6f20 Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Thu, 4 Jul 2019 15:37:34 +0300 Subject: [PATCH 11/28] add migrations folder --- docker-compose.yml | 2 +- web/docker_django/apps/todo/migrations/__init__.py | 0 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 web/docker_django/apps/todo/migrations/__init__.py diff --git a/docker-compose.yml b/docker-compose.yml index a9f397c..41ce2df 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,7 +11,7 @@ services: env_file: my.env environment: DEBUG: 'true' - command: bash -c "python manage.py makemigrations todo && python manage.py migrate && gunicorn docker_django.wsgi:application --reload -w 2 -b :8000" + command: bash -c "python manage.py makemigrations && python manage.py migrate && gunicorn docker_django.wsgi:application --reload -w 2 -b :8000" nginx: restart: always diff --git a/web/docker_django/apps/todo/migrations/__init__.py b/web/docker_django/apps/todo/migrations/__init__.py new file mode 100644 index 0000000..e69de29 From 3f21863ab520de9bc00068bdc88fdf7c99fff905 Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Thu, 4 Jul 2019 15:55:38 +0300 Subject: [PATCH 12/28] update readme --- README.md | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a02831d..ff32dc3 100644 --- a/README.md +++ b/README.md @@ -6,14 +6,32 @@ Featuring: - Docker Compose v1.23.2 - Docker Machine v0.16.1 - Python 3.7.3 +- MySQL 5.7 -Blog post -> https://realpython.com/blog/python/django-development-with-docker-compose-and-machine/ +Original Blog post -> https://realpython.com/blog/python/django-development-with-docker-compose-and-machine/ -### OS X Instructions +Building on the original repo, this repo adds the following capabilities; -1. Start new machine - `docker-machine create -d virtualbox dev;` +1. Uses MySQL instead of Postgresql +1. Runs migrations before starting django +1. Allows the use of an existing mysql db configured by the DB_* environment variables +1. Adds live reload capabaility for the source code + +### General Instructions + +1. Start new machine - `docker-machine create -d virtualbox dev` 1. Configure your shell to use the new machine environment - `eval $(docker-machine env dev)` -1. Build images - `docker-compose build` -1. Start services - `docker-compose up -d` -1. Create migrations - `docker-compose run web /usr/local/bin/python manage.py migrate` +1. Build and Start services - `docker-compose up -d` 1. Grab IP - `docker-machine ip dev` - and view in your browser + +If you encounter this error + +```sh +Cannot start service web: driver failed programming external connectivity on endpoint + failed: port is already allocated +Encountered errors while bringing up the project. +``` + +* Modify your env file and change the exposed ports on host +* Alternatively, shut down services on the host that are bound to the ports + From c968769f6ec5b4e8830df6e76b262cc86aeaefd2 Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Thu, 4 Jul 2019 16:05:38 +0300 Subject: [PATCH 13/28] update production compose file --- docker-compose.yml | 2 +- production.yml | 37 +++++++++++++++++++------------------ 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 41ce2df..2c31fa4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,7 +8,7 @@ services: - "${WEB_PORT}:8000" volumes: - ./web:/usr/src/app - env_file: my.env + env_file: .env environment: DEBUG: 'true' command: bash -c "python manage.py makemigrations && python manage.py migrate && gunicorn docker_django.wsgi:application --reload -w 2 -b :8000" diff --git a/production.yml b/production.yml index c6f5755..1d3c7ac 100644 --- a/production.yml +++ b/production.yml @@ -1,37 +1,26 @@ -version: '3' +version: '2.1' services: web: restart: always build: ./web - expose: + ports: - "8000" - links: - - postgres:postgres - - redis:redis volumes: - web-static:/usr/src/app/static env_file: .env - command: /usr/local/bin/gunicorn docker_django.wsgi:application -w 2 -b :8000 + command: bash -c "python manage.py makemigrations && python manage.py migrate && gunicorn docker_django.wsgi:application -w 2 -b :8000" nginx: restart: always - build: ./nginx/ + build: ./nginx ports: - - "80:80" + - "${NGINX_PORT}:80" volumes: - web-static:/www/static links: - web:web - postgres: - restart: always - image: postgres:latest - ports: - - "5432" - volumes: - - pgdata:/var/lib/postgresql/data/ - redis: restart: always image: redis:latest @@ -40,7 +29,19 @@ services: volumes: - redisdata:/data + mysql-db: + image: mysql:5.7 + environment: + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} + MYSQL_DATABASE: ${MYSQL_DATABASE} + MYSQL_USER: ${MYSQL_USER} + MYSQL_PASSWORD: ${MYSQL_PASSWORD} + ports: + - "3306" + volumes: + - mysql-vol:/var/lib/mysql + volumes: - web-static: - pgdata: + mysql-vol: redisdata: + web-static: From b1f5a90030682df5a5d5bb3bbe04033608a84f67 Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Fri, 5 Jul 2019 08:02:51 +0300 Subject: [PATCH 14/28] use pycopg-binary to get rid of warnings --- web/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/web/requirements.txt b/web/requirements.txt index f71dc19..f58ccf2 100644 --- a/web/requirements.txt +++ b/web/requirements.txt @@ -1,4 +1,5 @@ Django==2.1.7 gunicorn==19.9.0 redis==3.2.1 +psycopg2-binary mysql-connector-python==8.0.16 From 6efaf3245dfdcb2f208221e2c5de1641eaf5ea03 Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Fri, 5 Jul 2019 08:04:48 +0300 Subject: [PATCH 15/28] set database engine dynamically --- web/docker_django/settings.py | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/web/docker_django/settings.py b/web/docker_django/settings.py index e6f1409..2341de5 100644 --- a/web/docker_django/settings.py +++ b/web/docker_django/settings.py @@ -82,15 +82,27 @@ # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), # } # } +def get_engine(): + ''' + Set database engine based on DJANGO_DB_TYPE environment variable. + Default Engine is 'django.db.backends.postgresql_psycopg2' + This will be overridden by specifying DJANGO_DB_ENGINE environment variable + ''' + db_type = os.getenv('DB_TYPE', 'postgres').lower() + if db_type in ('mysql', 'mariadb'): + return 'mysql.connector.django' + if 'sqlite' in db_type: + return 'django.db.backends.sqlite3' + return 'django.db.backends.postgresql_psycopg2' DATABASES = { 'default': { - 'ENGINE': 'mysql.connector.django', - 'NAME': os.environ['DB_NAME'], - 'USER': os.environ['DB_USER'], - 'PASSWORD': os.environ['DB_PASS'], - 'HOST': os.environ['DB_HOST'], - 'PORT': os.environ['DB_PORT'] + 'ENGINE': os.getenv('DJANGO_DB_ENGINE', get_engine()), + 'NAME': os.environ['DJANGO_DB_NAME'], + 'USER': os.environ['DJANGO_DB_USER'], + 'PASSWORD': os.environ['DJANGO_DB_PASS'], + 'HOST': os.environ['DJANGO_DB_HOST'], + 'PORT': os.environ['DJANGO_DB_PORT'] } } @@ -116,4 +128,4 @@ # os.path.join(BASE_DIR, 'static'), # ) # print(STATICFILES_DIRS) -STATIC_ROOT = os.path.join(BASE_DIR, 'static') +STATIC_ROOT = os.path.join(BASE_DIR, 'static') \ No newline at end of file From 9d0b6248f65c7159102dfc5f0ce014993d602b07 Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Fri, 5 Jul 2019 08:57:57 +0300 Subject: [PATCH 16/28] update variable names --- web/docker_django/settings.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/web/docker_django/settings.py b/web/docker_django/settings.py index 2341de5..8e9f046 100644 --- a/web/docker_django/settings.py +++ b/web/docker_django/settings.py @@ -84,9 +84,9 @@ # } def get_engine(): ''' - Set database engine based on DJANGO_DB_TYPE environment variable. + Set database engine based on DB_TYPE environment variable. Default Engine is 'django.db.backends.postgresql_psycopg2' - This will be overridden by specifying DJANGO_DB_ENGINE environment variable + This will be overridden by specifying DB_ENGINE environment variable ''' db_type = os.getenv('DB_TYPE', 'postgres').lower() if db_type in ('mysql', 'mariadb'): @@ -97,12 +97,12 @@ def get_engine(): DATABASES = { 'default': { - 'ENGINE': os.getenv('DJANGO_DB_ENGINE', get_engine()), - 'NAME': os.environ['DJANGO_DB_NAME'], - 'USER': os.environ['DJANGO_DB_USER'], - 'PASSWORD': os.environ['DJANGO_DB_PASS'], - 'HOST': os.environ['DJANGO_DB_HOST'], - 'PORT': os.environ['DJANGO_DB_PORT'] + 'ENGINE': os.getenv('DB_ENGINE', get_engine()), + 'NAME': os.environ['DB_NAME'], + 'USER': os.environ['DB_USER'], + 'PASSWORD': os.environ['DB_PASS'], + 'HOST': os.environ['DB_HOST'], + 'PORT': os.environ['DB_PORT'] } } From 2af875d6b707bda733d30e214667168d456c732b Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Fri, 5 Jul 2019 08:59:05 +0300 Subject: [PATCH 17/28] update production compose file --- production.yml | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/production.yml b/production.yml index 1d3c7ac..6eb4e0f 100644 --- a/production.yml +++ b/production.yml @@ -6,6 +6,7 @@ services: build: ./web ports: - "8000" + entrypoint: ["./wait-for-it.sh", "${DJANGO_DB_HOST}:${DJANGO_DB_PORT}", "--strict", "--timeout=300", "--"] volumes: - web-static:/usr/src/app/static env_file: .env @@ -15,7 +16,7 @@ services: restart: always build: ./nginx ports: - - "${NGINX_PORT}:80" + - "${HOST_NGINX_PORT}:80" volumes: - web-static:/www/static links: @@ -29,17 +30,25 @@ services: volumes: - redisdata:/data - mysql-db: - image: mysql:5.7 + database: + build: ./${DB_TYPE} + image: ${DB_TYPE}_db environment: - MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} - MYSQL_DATABASE: ${MYSQL_DATABASE} - MYSQL_USER: ${MYSQL_USER} - MYSQL_PASSWORD: ${MYSQL_PASSWORD} + # POSTGRES SPECIFIC + POSTGRES_DB: ${DB_NAME} + POSTGRES_USER: ${DB_USER} + POSTGRES_PASSWORD: ${DB_PASS} + # MYSQL SPECIFIC + MYSQL_DATABASE: ${DB_NAME} + MYSQL_USER: ${DB_USER} + MYSQL_PASSWORD: ${DB_PASS} + MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} ports: - - "3306" + - "${HOST_DATABASE_PORT:-$DB_PORT}:${DB_PORT}" volumes: - mysql-vol:/var/lib/mysql + - pgdata:/var/lib/postgresql/data/ + container_name: ${DB_TYPE}_db volumes: mysql-vol: From 2d7dae358b8982035521cb5e7026f0009a090541 Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Fri, 5 Jul 2019 08:59:25 +0300 Subject: [PATCH 18/28] update local compose file --- docker-compose.yml | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 2c31fa4..ce0dffc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,19 +5,20 @@ services: restart: always build: ./web ports: - - "${WEB_PORT}:8000" + - "${HOST_WEB_PORT}:8000" volumes: - ./web:/usr/src/app + entrypoint: ["./wait-for-it.sh", "${DJANGO_DB_HOST}:${DJANGO_DB_PORT}", "--strict", "--timeout=300", "--"] env_file: .env environment: DEBUG: 'true' - command: bash -c "python manage.py makemigrations && python manage.py migrate && gunicorn docker_django.wsgi:application --reload -w 2 -b :8000" + command: bash -c "python manage.py makemigrations && python manage.py migrate && gunicorn docker_django.wsgi:application --reload --log-level=debug -w 2 -b :8000" nginx: restart: always build: ./nginx ports: - - "${NGINX_PORT}:80" + - "${HOST_NGINX_PORT}:80" volumes: - ./web/static:/www/static - ./nginx/sites-enabled:/etc/nginx/sites-enabled @@ -28,23 +29,31 @@ services: restart: always image: redis:latest ports: - - "${REDIS_PORT}:6379" + - "${HOST_REDIS_PORT}:6379" volumes: - redisdata:/data - - mysql-db: - image: mysql:5.7 + + database: + build: ./${DB_TYPE} + image: ${DB_TYPE}_db environment: - MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} - MYSQL_DATABASE: ${MYSQL_DATABASE} - MYSQL_USER: ${MYSQL_USER} - MYSQL_PASSWORD: ${MYSQL_PASSWORD} + # POSTGRES SPECIFIC + POSTGRES_DB: ${DB_NAME} + POSTGRES_USER: ${DB_USER} + POSTGRES_PASSWORD: ${DB_PASS} + # MYSQL SPECIFIC + MYSQL_DATABASE: ${DB_NAME} + MYSQL_USER: ${DB_USER} + MYSQL_PASSWORD: ${DB_PASS} + MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} ports: - - "${MYSQL_PORT}:3306" + - "${HOST_DATABASE_PORT:-$DB_PORT}:${DB_PORT}" volumes: - mysql-vol:/var/lib/mysql - - ./mysql/:/docker-entrypoint-initdb.d/ + - pgdata:/var/lib/postgresql/data/ + container_name: ${DB_TYPE}_db volumes: mysql-vol: + pgdata: redisdata: From 21800854e139c62c16c4d8d18e8a3477c9e984ef Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Fri, 5 Jul 2019 09:00:20 +0300 Subject: [PATCH 19/28] update README --- README.md | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ff32dc3..c781daf 100644 --- a/README.md +++ b/README.md @@ -6,16 +6,19 @@ Featuring: - Docker Compose v1.23.2 - Docker Machine v0.16.1 - Python 3.7.3 +- Postgresql - MySQL 5.7 Original Blog post -> https://realpython.com/blog/python/django-development-with-docker-compose-and-machine/ Building on the original repo, this repo adds the following capabilities; -1. Uses MySQL instead of Postgresql +1. Is compatible with the original repo and simplifies running the compose stack +1. Adds flexibility by using environment variables to make the service highly configurable +1. Allows switching between postgres or mysql database. +1. Allows the use of an existing database configured by the DB_TYPE=remote & DB_* environment variables 1. Runs migrations before starting django -1. Allows the use of an existing mysql db configured by the DB_* environment variables -1. Adds live reload capabaility for the source code +1. Adds live reload capability for the django code ### General Instructions @@ -24,6 +27,18 @@ Building on the original repo, this repo adds the following capabilities; 1. Build and Start services - `docker-compose up -d` 1. Grab IP - `docker-machine ip dev` - and view in your browser +### Advanced Usage +To use existing remote database, change the following in .env; +1. DJANGO_DB_* variables to match your remote database +1. DB_TYPE=remote +1. Run `docker-compose up -d` + +To switch databases, change the following in .env; +1. DB_TYPE to mysql, postgres or sqlite +1. If database was already started previously, run `docker-compose stop database && docker-compose rm -f database` +1. Run `docker-compose up -d` + +### Troubleshooting If you encounter this error ```sh @@ -34,4 +49,6 @@ Encountered errors while bringing up the project. * Modify your env file and change the exposed ports on host * Alternatively, shut down services on the host that are bound to the ports +* Once done run `docker-compose up -d` + From 07f6da5eca154cb7b907d6fd5a3c6e269be89a94 Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Fri, 5 Jul 2019 09:00:39 +0300 Subject: [PATCH 20/28] update .env file --- .env | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/.env b/.env index f9d13bb..698d121 100644 --- a/.env +++ b/.env @@ -1,19 +1,26 @@ -# django/web environment variables +# Environment variables for django/web service. +# Defining them here allows django to connect with compose database plus remote database. SECRET_KEY=5(15ds+i2+%ik6z&!yer+ga9m=e%jcqiz_5wszg)r-z!2--b2d -DB_NAME=todo +DB_NAME=tododb DB_USER=todo DB_PASS=pass -DB_HOST=mysql-db -DB_PORT=3306 +DB_HOST=database +# Options are: 5432 for postgres, 3306 for mysql, or available remote port for remote database. +DB_PORT=5432 +# Options are: postgres, mysql or remote for remote database. +DB_TYPE=postgres +# You must specify this if you set DB_TYPE = remote. Available options are; +# For postgres: django.db.backends.postgresql_psycopg2 +# For mysql: mysql.connector.django +# DB_ENGINE=mysql.connector.django -# mysql database variables -MYSQL_ROOT_PASSWORD=password -MYSQL_DATABASE=todo -MYSQL_USER=todo -MYSQL_PASSWORD=pass +# For mysql +DB_ROOT_PASSWORD=password -# expose ports on host -WEB_PORT=8000 -NGINX_PORT=80 -REDIS_PORT=6379 -MYSQL_PORT=3306 + +# Expose ports on host, change port if already used on host. +# Note that the production deployment only exposes the database & nginx port. +HOST_WEB_PORT=8000 +HOST_NGINX_PORT=80 +HOST_REDIS_PORT=6379 +HOST_DATABASE_PORT= From 3ec872bb9e07fe13a738a73634df43e94fd806a1 Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Fri, 5 Jul 2019 09:01:22 +0300 Subject: [PATCH 21/28] add .sql files to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 510d1cb..2c188ee 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ env __pycache__ .venv .cache +.sql \ No newline at end of file From ba1f402cd9f368a2f49754818242548e319fba4d Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Fri, 5 Jul 2019 09:06:16 +0300 Subject: [PATCH 22/28] fix database port definitions --- docker-compose.yml | 4 ++-- production.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index ce0dffc..6136142 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,7 +8,7 @@ services: - "${HOST_WEB_PORT}:8000" volumes: - ./web:/usr/src/app - entrypoint: ["./wait-for-it.sh", "${DJANGO_DB_HOST}:${DJANGO_DB_PORT}", "--strict", "--timeout=300", "--"] + entrypoint: ["./wait-for-it.sh", "${DB_HOST}:${DB_PORT}", "--strict", "--timeout=300", "--"] env_file: .env environment: DEBUG: 'true' @@ -47,7 +47,7 @@ services: MYSQL_PASSWORD: ${DB_PASS} MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} ports: - - "${HOST_DATABASE_PORT:-$DB_PORT}:${DB_PORT}" + - "${HOST_DATABASE_PORT}:${DB_PORT}" volumes: - mysql-vol:/var/lib/mysql - pgdata:/var/lib/postgresql/data/ diff --git a/production.yml b/production.yml index 6eb4e0f..b3b209e 100644 --- a/production.yml +++ b/production.yml @@ -6,7 +6,7 @@ services: build: ./web ports: - "8000" - entrypoint: ["./wait-for-it.sh", "${DJANGO_DB_HOST}:${DJANGO_DB_PORT}", "--strict", "--timeout=300", "--"] + entrypoint: ["./wait-for-it.sh", "${DB_HOST}:${DB_PORT}", "--strict", "--timeout=300", "--"] volumes: - web-static:/usr/src/app/static env_file: .env @@ -44,7 +44,7 @@ services: MYSQL_PASSWORD: ${DB_PASS} MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} ports: - - "${HOST_DATABASE_PORT:-$DB_PORT}:${DB_PORT}" + - "${HOST_DATABASE_PORT}:${DB_PORT}" volumes: - mysql-vol:/var/lib/mysql - pgdata:/var/lib/postgresql/data/ From dad345da167d71b57c66988d25ef7b44bca8c538 Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Fri, 5 Jul 2019 10:30:41 +0300 Subject: [PATCH 23/28] update .env host port variables --- .env | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.env b/.env index 698d121..5b5d3a2 100644 --- a/.env +++ b/.env @@ -1,7 +1,6 @@ # Environment variables for django/web service. -# Defining them here allows django to connect with compose database plus remote database. SECRET_KEY=5(15ds+i2+%ik6z&!yer+ga9m=e%jcqiz_5wszg)r-z!2--b2d -DB_NAME=tododb +DB_NAME=django_db DB_USER=todo DB_PASS=pass DB_HOST=database @@ -18,9 +17,10 @@ DB_TYPE=postgres DB_ROOT_PASSWORD=password -# Expose ports on host, change port if already used on host. +# Expose ports on host, e.g. Set HOST_NGINX_PORT=80. +# You will need to change the port if already used on host. # Note that the production deployment only exposes the database & nginx port. -HOST_WEB_PORT=8000 -HOST_NGINX_PORT=80 -HOST_REDIS_PORT=6379 -HOST_DATABASE_PORT= +HOST_WEB_PORT=0 +HOST_NGINX_PORT=0 +HOST_REDIS_PORT=0 +HOST_DATABASE_PORT=0 From 4548e7f8db9971b75442fd711c7984bc17695082 Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Fri, 5 Jul 2019 12:09:06 +0300 Subject: [PATCH 24/28] add DB_TYPE env variable to web so it can reload --- docker-compose.yml | 2 +- production.yml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 6136142..8bbd79a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,6 +12,7 @@ services: env_file: .env environment: DEBUG: 'true' + DB_TYPE: ${DB_TYPE} command: bash -c "python manage.py makemigrations && python manage.py migrate && gunicorn docker_django.wsgi:application --reload --log-level=debug -w 2 -b :8000" nginx: @@ -51,7 +52,6 @@ services: volumes: - mysql-vol:/var/lib/mysql - pgdata:/var/lib/postgresql/data/ - container_name: ${DB_TYPE}_db volumes: mysql-vol: diff --git a/production.yml b/production.yml index b3b209e..c10ac29 100644 --- a/production.yml +++ b/production.yml @@ -10,6 +10,8 @@ services: volumes: - web-static:/usr/src/app/static env_file: .env + environment: + DB_TYPE: ${DB_TYPE} command: bash -c "python manage.py makemigrations && python manage.py migrate && gunicorn docker_django.wsgi:application -w 2 -b :8000" nginx: @@ -48,7 +50,6 @@ services: volumes: - mysql-vol:/var/lib/mysql - pgdata:/var/lib/postgresql/data/ - container_name: ${DB_TYPE}_db volumes: mysql-vol: From 1025427b3fc24083425cfecf898e0e0b230150b9 Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Fri, 5 Jul 2019 12:09:27 +0300 Subject: [PATCH 25/28] add examples to README --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index c781daf..15b448f 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,22 @@ Building on the original repo, this repo adds the following capabilities; 1. Start new machine - `docker-machine create -d virtualbox dev` 1. Configure your shell to use the new machine environment - `eval $(docker-machine env dev)` +1. (Optional) Update .env to match your requirements e.g. Set HOST_NGINX_PORT=80 1. Build and Start services - `docker-compose up -d` 1. Grab IP - `docker-machine ip dev` - and view in your browser + Example: + ```sh + $ docker-machine ip dev + 192.168.99.101 + ``` + The app will be available at http://: +1. (Optional) If you did not set HOST_NGINX_PORT i.e. HOST_NGINX_PORT=0, show Ports - `docker-compose ps` + Example: + ```sh + $ docker-compose ps + dockerizingdjango_nginx_1 /usr/sbin/nginx Up 0.0.0.0:33126->80/tcp + ``` + In this example, the app is available at http://192.168.99.101:33126. ### Advanced Usage To use existing remote database, change the following in .env; @@ -38,6 +52,9 @@ To switch databases, change the following in .env; 1. If database was already started previously, run `docker-compose stop database && docker-compose rm -f database` 1. Run `docker-compose up -d` +To clean up, reset or start over +1. Run `docker-compose down -v`. Note that that this will delete all your containers and volumes defined in the compose file. + ### Troubleshooting If you encounter this error From 8a3ddc26022583d7ba4f483aa4c7b4e6cd932238 Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Fri, 5 Jul 2019 13:10:58 +0300 Subject: [PATCH 26/28] Restore compose version to 3 --- docker-compose.yml | 2 +- production.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 8bbd79a..fb4f2da 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: '2.1' +version: '3' services: web: diff --git a/production.yml b/production.yml index c10ac29..65fede3 100644 --- a/production.yml +++ b/production.yml @@ -1,4 +1,4 @@ -version: '2.1' +version: '3' services: web: From c8ea918c9f9309e8727d2c4dfc102921163a1057 Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Fri, 5 Jul 2019 18:11:12 +0300 Subject: [PATCH 27/28] add db folders --- mysql/Dockerfile | 1 + postgres/Dockerfile | 1 + remote/Dockerfile | 4 ++++ 3 files changed, 6 insertions(+) create mode 100644 mysql/Dockerfile create mode 100644 postgres/Dockerfile create mode 100644 remote/Dockerfile diff --git a/mysql/Dockerfile b/mysql/Dockerfile new file mode 100644 index 0000000..30d16c5 --- /dev/null +++ b/mysql/Dockerfile @@ -0,0 +1 @@ +FROM mysql:5.7 \ No newline at end of file diff --git a/postgres/Dockerfile b/postgres/Dockerfile new file mode 100644 index 0000000..0cda63a --- /dev/null +++ b/postgres/Dockerfile @@ -0,0 +1 @@ +FROM postgres:latest \ No newline at end of file diff --git a/remote/Dockerfile b/remote/Dockerfile new file mode 100644 index 0000000..a7a0aa8 --- /dev/null +++ b/remote/Dockerfile @@ -0,0 +1,4 @@ +# This is an idle image to dynamically replace any component if disabled. + +FROM alpine:3.7 +CMD sleep 1000000d \ No newline at end of file From cdacb31ce4648b5d2189133dc55d379b8e98019d Mon Sep 17 00:00:00 2001 From: jawabuu <49921621+jawabuu@users.noreply.github.com> Date: Fri, 5 Jul 2019 19:23:14 +0300 Subject: [PATCH 28/28] add wait-for-it script --- web/wait-for-it.sh | 178 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 web/wait-for-it.sh diff --git a/web/wait-for-it.sh b/web/wait-for-it.sh new file mode 100644 index 0000000..071c2be --- /dev/null +++ b/web/wait-for-it.sh @@ -0,0 +1,178 @@ +#!/usr/bin/env bash +# Use this script to test if a given TCP host/port are available + +WAITFORIT_cmdname=${0##*/} + +echoerr() { if [[ $WAITFORIT_QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } + +usage() +{ + cat << USAGE >&2 +Usage: + $WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args] + -h HOST | --host=HOST Host or IP under test + -p PORT | --port=PORT TCP port under test + Alternatively, you specify the host and port as host:port + -s | --strict Only execute subcommand if the test succeeds + -q | --quiet Don't output any status messages + -t TIMEOUT | --timeout=TIMEOUT + Timeout in seconds, zero for no timeout + -- COMMAND ARGS Execute command with args after the test finishes +USAGE + exit 1 +} + +wait_for() +{ + if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then + echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT" + else + echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout" + fi + WAITFORIT_start_ts=$(date +%s) + while : + do + if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then + nc -z $WAITFORIT_HOST $WAITFORIT_PORT + WAITFORIT_result=$? + else + (echo > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1 + WAITFORIT_result=$? + fi + if [[ $WAITFORIT_result -eq 0 ]]; then + WAITFORIT_end_ts=$(date +%s) + echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds" + break + fi + sleep 1 + done + return $WAITFORIT_result +} + +wait_for_wrapper() +{ + # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 + if [[ $WAITFORIT_QUIET -eq 1 ]]; then + timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT & + else + timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT & + fi + WAITFORIT_PID=$! + trap "kill -INT -$WAITFORIT_PID" INT + wait $WAITFORIT_PID + WAITFORIT_RESULT=$? + if [[ $WAITFORIT_RESULT -ne 0 ]]; then + echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT" + fi + return $WAITFORIT_RESULT +} + +# process arguments +while [[ $# -gt 0 ]] +do + case "$1" in + *:* ) + WAITFORIT_hostport=(${1//:/ }) + WAITFORIT_HOST=${WAITFORIT_hostport[0]} + WAITFORIT_PORT=${WAITFORIT_hostport[1]} + shift 1 + ;; + --child) + WAITFORIT_CHILD=1 + shift 1 + ;; + -q | --quiet) + WAITFORIT_QUIET=1 + shift 1 + ;; + -s | --strict) + WAITFORIT_STRICT=1 + shift 1 + ;; + -h) + WAITFORIT_HOST="$2" + if [[ $WAITFORIT_HOST == "" ]]; then break; fi + shift 2 + ;; + --host=*) + WAITFORIT_HOST="${1#*=}" + shift 1 + ;; + -p) + WAITFORIT_PORT="$2" + if [[ $WAITFORIT_PORT == "" ]]; then break; fi + shift 2 + ;; + --port=*) + WAITFORIT_PORT="${1#*=}" + shift 1 + ;; + -t) + WAITFORIT_TIMEOUT="$2" + if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fi + shift 2 + ;; + --timeout=*) + WAITFORIT_TIMEOUT="${1#*=}" + shift 1 + ;; + --) + shift + WAITFORIT_CLI=("$@") + break + ;; + --help) + usage + ;; + *) + echoerr "Unknown argument: $1" + usage + ;; + esac +done + +if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; then + echoerr "Error: you need to provide a host and port to test." + usage +fi + +WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15} +WAITFORIT_STRICT=${WAITFORIT_STRICT:-0} +WAITFORIT_CHILD=${WAITFORIT_CHILD:-0} +WAITFORIT_QUIET=${WAITFORIT_QUIET:-0} + +# check to see if timeout is from busybox? +WAITFORIT_TIMEOUT_PATH=$(type -p timeout) +WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH) +if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then + WAITFORIT_ISBUSY=1 + WAITFORIT_BUSYTIMEFLAG="-t" + +else + WAITFORIT_ISBUSY=0 + WAITFORIT_BUSYTIMEFLAG="" +fi + +if [[ $WAITFORIT_CHILD -gt 0 ]]; then + wait_for + WAITFORIT_RESULT=$? + exit $WAITFORIT_RESULT +else + if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then + wait_for_wrapper + WAITFORIT_RESULT=$? + else + wait_for + WAITFORIT_RESULT=$? + fi +fi + +if [[ $WAITFORIT_CLI != "" ]]; then + if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then + echoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess" + exit $WAITFORIT_RESULT + fi + exec "${WAITFORIT_CLI[@]}" +else + exit $WAITFORIT_RESULT +fi