├── .env-db ├── .gitignore ├── LICENSE ├── README.md ├── commands.md ├── data ├── container.txt ├── custom.css ├── hello.txt ├── helloworld.txt └── index.html ├── django-app ├── .devcontainer │ └── devcontainer.json ├── .env-dev ├── .env-dj ├── Dockerfile.dev ├── Dockerfile.django-app ├── cfehome │ ├── __init__.py │ ├── asgi.py │ ├── celery │ │ ├── __init__.py │ │ └── conf.py │ ├── db.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── django ├── manage.py ├── requirements.txt ├── run-worker.sh ├── run.sh ├── static │ └── css │ │ └── custom.css ├── staticfiles │ └── blank-on-purpose.txt ├── todo.md └── triggers │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ └── __init__.py │ ├── models.py │ ├── tasks.py │ ├── tests.py │ └── views.py ├── docker-compose.dev.yaml ├── docker-compose.hub.yaml ├── docker-compose.yaml ├── docker-dc.code-workspace ├── express-app ├── Dockerfile.express-app ├── commands.md ├── package.json ├── run.sh └── server.js ├── go-app ├── Dockerfile.go-app ├── commands.md ├── run.sh └── server.go ├── nginx ├── Dockerfile.nginx ├── commands.md ├── index.html ├── static.conf └── world.html ├── php-app ├── Dockerfile.php-app ├── commands.md ├── index.php ├── run.sh └── super.php ├── py-app ├── Dockerfile.py-app ├── commands.md ├── hello.txt ├── requirements.txt ├── run.sh └── server.py └── staticfiles └── blank.txt /.env-db: -------------------------------------------------------------------------------- 1 | POSTGRES_DB=dockerdc 2 | POSTGRES_PASSWORD=mysecretpassword 3 | POSTGRES_USER=myuser 4 | POSTGRES_HOST=db 5 | POSTGRES_PORT=5432 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | staticfiles/admin/ 2 | staticfiles/css/ 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | .eggs/ 19 | lib/ 20 | lib64/ 21 | parts/ 22 | sdist/ 23 | var/ 24 | wheels/ 25 | pip-wheel-metadata/ 26 | share/python-wheels/ 27 | *.egg-info/ 28 | .installed.cfg 29 | *.egg 30 | MANIFEST 31 | 32 | # PyInstaller 33 | # Usually these files are written by a python script from a template 34 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 35 | *.manifest 36 | *.spec 37 | 38 | # Installer logs 39 | pip-log.txt 40 | pip-delete-this-directory.txt 41 | 42 | # Unit test / coverage reports 43 | htmlcov/ 44 | .tox/ 45 | .nox/ 46 | .coverage 47 | .coverage.* 48 | .cache 49 | nosetests.xml 50 | coverage.xml 51 | *.cover 52 | *.py,cover 53 | .hypothesis/ 54 | .pytest_cache/ 55 | 56 | # Translations 57 | *.mo 58 | *.pot 59 | 60 | # Django stuff: 61 | *.log 62 | local_settings.py 63 | db.sqlite3 64 | db.sqlite3-journal 65 | 66 | # Flask stuff: 67 | instance/ 68 | .webassets-cache 69 | 70 | # Scrapy stuff: 71 | .scrapy 72 | 73 | # Sphinx documentation 74 | docs/_build/ 75 | 76 | # PyBuilder 77 | target/ 78 | 79 | # Jupyter Notebook 80 | .ipynb_checkpoints 81 | 82 | # IPython 83 | profile_default/ 84 | ipython_config.py 85 | 86 | # pyenv 87 | .python-version 88 | 89 | # pipenv 90 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 91 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 92 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 93 | # install all needed dependencies. 94 | #Pipfile.lock 95 | 96 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 97 | __pypackages__/ 98 | 99 | # Celery stuff 100 | celerybeat-schedule 101 | celerybeat.pid 102 | 103 | # SageMath parsed files 104 | *.sage.py 105 | 106 | # Environments 107 | .env 108 | .venv 109 | env/ 110 | venv/ 111 | ENV/ 112 | env.bak/ 113 | venv.bak/ 114 | 115 | # Spyder project settings 116 | .spyderproject 117 | .spyproject 118 | 119 | # Rope project settings 120 | .ropeproject 121 | 122 | # mkdocs documentation 123 | /site 124 | 125 | # mypy 126 | .mypy_cache/ 127 | .dmypy.json 128 | dmypy.json 129 | 130 | # Pyre type checker 131 | .pyre/ 132 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Coding For Entrepreneurs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Docker-Docker-Compose Logo](https://static.codingforentrepreneurs.com/media/projects/docker-and-docker-compose/images/share/Docker__Docker_Compose.jpg)](https://www.codingforentrepreneurs.com/projects/docker-and-docker-compose) 2 | 3 | # [Docker & Docker Compose](https://www.codingforentrepreneurs.com/projects/docker-and-docker-compose) 4 | 5 | 6 | **Docker** helps us isolate our apps from everything else. It's *almost* as if our apps have their very own computer and I think that's pretty cool. 7 | 8 | **Docker Compose** helps us build local networks with many apps attached to it. 9 | 10 | This series will show you the fundamentals of using both in together. 11 | 12 | But why? 13 | 14 | Let's pretend I need Django, Express.js, and FastAPI to run on the *same domain*. Django will handle all the primary routes, Express.js will handle `/notifications` routes, FastAPI will handle the `/api/` routes. 15 | 16 | But how do we run these all on the *same domain*? **nginx** to the rescue! That's true, nginx can help us run all of these apps as illustrated above. 17 | 18 | But there's another problem. How can I use Docker for each of these apps? 19 | 20 | This is where **docker compose** comes in. **Docker Compose** will orchestrate containers in a network of their own. 21 | 22 | **Uh oh! This sounds complicated...** 23 | 24 | That's true. This does sound complicated but it's not. It's really just a bunch of configuration to get this stuff working correctly. Once you understand it fully, you'll be ready to use it in all kinds of projects. 25 | 26 | The goal of this series is to unpack what I mentioned above while building something real. 27 | -------------------------------------------------------------------------------- /commands.md: -------------------------------------------------------------------------------- 1 | ``` 2 | docker compose build --no-cache 3 | ``` 4 | 5 | 6 | ``` 7 | docker compose up --build 8 | ``` 9 | 10 | ``` 11 | docker compose down 12 | ``` 13 | 14 | 15 | 16 | Delete all containers 17 | ``` 18 | docker rm -vf $(docker ps -a -q) 19 | ``` 20 | 21 | Delete all images 22 | ``` 23 | docker rmi -f $(docker images -a -q) 24 | ``` 25 | Found [here](https://stackoverflow.com/a/44785784) 26 | 27 | 28 | 29 | Automated Volume Creation 30 | ``` 31 | docker run -v myvol:/where/to/mount container-image 32 | ``` 33 | > `docker run --name ironman-1 -v ironmanvol:/app/data3 py-app-1` 34 | ``` 35 | docker volume ls 36 | ``` 37 | 38 | Manual Volume Creation 39 | ``` 40 | docker run -v /abs/path/to/local/data/:/where/to/mount/ py-app-1 41 | ``` 42 | > `docker run --name ironman -v /Users/cfe/Dev/docker-dc/data/:/app/data py-app-1` 43 | 44 | 45 | 46 | ### Databases 47 | 48 | ``` 49 | docker pull postgres 50 | ``` 51 | 52 | 53 | ``` 54 | docker run -p 6543:5432 -e POSTGRES_USER=myuser -e POSTGRES_PASSWORD=mytestpw postgres 55 | ``` 56 | 57 | ``` 58 | docker run -it --rm postgres /bin/bash 59 | # psql -U myuser 60 | ``` 61 | 62 | 63 | 64 | ## Pushing to Docker Hub 65 | 66 | ### 1. Tag images for dockerhub: 67 | 68 | Tags must be: 69 | `docker-hub-username`/`reponame` 70 | or 71 | `docker-hub-username`/`reponame:v1` 72 | 73 | Such as: 74 | 75 | ``` 76 | docker build -t codingforentrepreneurs/myrepo -f Dockerfile . 77 | ``` 78 | 79 | or 80 | 81 | ``` 82 | docker build -t codingforentrepreneurs/myrepo:v3 -f Dockerfile . 83 | ``` 84 | 85 | or 86 | 87 | ``` 88 | docker image ls 89 | ``` 90 | I have an image with the id of `f52105e1ba2b` that I am going to tag to `codingforentrepreneurs/docker-dc-goapp` 91 | 92 | ``` 93 | docker tag f52105e1ba2b codingforentrepreneurs/docker-dc-goapp 94 | ``` 95 | 96 | The format is 97 | ``` 98 | docker tag 99 | ``` 100 | 101 | ### 2. Push with new tag: 102 | 103 | ``` 104 | docker push 105 | ``` 106 | like 107 | ``` 108 | docker push codingforentrepreneurs/docker-dc-goapp 109 | ``` 110 | -------------------------------------------------------------------------------- /data/container.txt: -------------------------------------------------------------------------------- 1 | hello from container 2 | -------------------------------------------------------------------------------- /data/custom.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: red; 3 | } -------------------------------------------------------------------------------- /data/hello.txt: -------------------------------------------------------------------------------- 1 | hello from vscode local editor -------------------------------------------------------------------------------- /data/helloworld.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/Docker-Docker-Compose/665c5c01762ee95546dd9a7902159e530a7932f2/data/helloworld.txt -------------------------------------------------------------------------------- /data/index.html: -------------------------------------------------------------------------------- 1 | 2 |

This is working

-------------------------------------------------------------------------------- /django-app/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: 2 | // https://github.com/microsoft/vscode-dev-containers/tree/v0.166.1/containers/docker-existing-dockerfile 3 | { 4 | "name": "Existing Dockerfile", 5 | 6 | // Sets the run context to one level up instead of the .devcontainer folder. 7 | "context": "..", 8 | 9 | // Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename. 10 | "dockerFile": "../Dockerfile.dev", 11 | 12 | // Set *default* container specific settings.json values on container create. 13 | "settings": { 14 | "terminal.integrated.shell.linux": null 15 | }, 16 | 17 | // Add the IDs of extensions you want installed when the container is created. 18 | "extensions": [] 19 | 20 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 21 | // "forwardPorts": [], 22 | 23 | // Uncomment the next line to run commands after the container is created - for example installing curl. 24 | // "postCreateCommand": "apt-get update && apt-get install -y curl", 25 | 26 | // Uncomment when using a ptrace-based debugger like C++, Go, and Rust 27 | // "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ], 28 | 29 | // Uncomment to use the Docker CLI from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker. 30 | // "mounts": [ "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind" ], 31 | 32 | // Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root. 33 | // "remoteUser": "vscode" 34 | } 35 | -------------------------------------------------------------------------------- /django-app/.env-dev: -------------------------------------------------------------------------------- 1 | DJANGO_SUPERUSER_USERNAME=admin 2 | DJANGO_SUPERUSER_PASSWORD=mydjangopw 3 | DJANGO_SUERPUSER_EMAIL=hello@teamcfe.com 4 | 5 | POSTGRES_DB=dockerdc 6 | POSTGRES_PASSWORD=mysecretpassword 7 | POSTGRES_USER=myuser 8 | POSTGRES_HOST=host.docker.internal 9 | POSTGRES_PORT=5433 10 | 11 | REDIS_HOST=host.docker.internal 12 | REDIS_PORT=6380 -------------------------------------------------------------------------------- /django-app/.env-dj: -------------------------------------------------------------------------------- 1 | DJANGO_SUPERUSER_USERNAME=admin 2 | DJANGO_SUPERUSER_PASSWORD=mydjangopw 3 | DJANGO_SUERPUSER_EMAIL=hello@teamcfe.com -------------------------------------------------------------------------------- /django-app/Dockerfile.dev: -------------------------------------------------------------------------------- 1 | FROM python:3.9-slim 2 | 3 | COPY . /app 4 | WORKDIR /app 5 | 6 | RUN pip install pip --upgrade 7 | RUN pip install -r requirements.txt 8 | 9 | RUN chmod +x run.sh 10 | RUN chmod +x run-worker.sh 11 | 12 | 13 | ENV USE_DOTENV_PKG=1 14 | 15 | CMD ["./run.sh"] -------------------------------------------------------------------------------- /django-app/Dockerfile.django-app: -------------------------------------------------------------------------------- 1 | FROM python:3.9-slim 2 | 3 | COPY . /app 4 | WORKDIR /app 5 | 6 | RUN pip install pip --upgrade 7 | RUN pip install -r requirements.txt 8 | 9 | RUN chmod +x run.sh 10 | RUN chmod +x run-worker.sh 11 | 12 | CMD ["./run.sh"] -------------------------------------------------------------------------------- /django-app/cfehome/__init__.py: -------------------------------------------------------------------------------- 1 | from .celery import app as celery_app 2 | 3 | __all__ = ('celery_app', ) -------------------------------------------------------------------------------- /django-app/cfehome/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for cfehome project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'cfehome.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /django-app/cfehome/celery/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pathlib 3 | import dotenv 4 | from celery import Celery 5 | 6 | 7 | USE_DOTENV = os.environ.get("USE_DOTENV_PKG") 8 | if str(USE_DOTENV) == "1": 9 | base_path = pathlib.Path(__file__).resolve().parent.parent.parent 10 | dotenv.read_dotenv(base_path / ".env-dev") 11 | 12 | # from django.conf import settings 13 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'cfehome.settings') 14 | 15 | REDIS_HOST = os.environ.get("REDIS_HOST", "localhost") 16 | REDIS_PORT = os.environ.get("REDIS_PORT", 6379) 17 | REDIS_URL = f"redis://{REDIS_HOST}:{REDIS_PORT}" 18 | 19 | app = Celery('cfehome') 20 | app.config_from_object("django.conf:settings", namespace='CELERY') 21 | app.autodiscover_tasks() 22 | app.conf.broker_url = REDIS_URL 23 | app.conf.beat_scheduler = "django_celery_beat.schedulers.DatabaseScheduler" 24 | -------------------------------------------------------------------------------- /django-app/cfehome/celery/conf.py: -------------------------------------------------------------------------------- 1 | CELERY_RESULT_BACKEND = "django-db" -------------------------------------------------------------------------------- /django-app/cfehome/db.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | ''' 4 | POSTGRES_DB=dockerdc 5 | POSTGRES_PASSWORD=mysecretpassword 6 | POSTGRES_USER=myuser 7 | POSTGRES_HOST=db 8 | POSTGRES_PORT=5432 9 | ''' 10 | POSTGRES_DB=os.environ.get("POSTGRES_DB") 11 | POSTGRES_PASSWORD=os.environ.get("POSTGRES_PASSWORD") 12 | POSTGRES_USER=os.environ.get("POSTGRES_USER") 13 | POSTGRES_HOST=os.environ.get("POSTGRES_HOST") 14 | POSTGRES_PORT=os.environ.get("POSTGRES_PORT") 15 | 16 | POSTGRES_READY = ( 17 | POSTGRES_DB is not None and 18 | POSTGRES_PASSWORD is not None and 19 | POSTGRES_USER is not None and 20 | POSTGRES_HOST is not None and 21 | POSTGRES_PORT is not None 22 | ) 23 | 24 | if POSTGRES_READY: 25 | DATABASES = { 26 | "default": { 27 | "ENGINE": "django.db.backends.postgresql", 28 | "NAME": POSTGRES_DB, 29 | "USER": POSTGRES_USER, 30 | "PASSWORD":POSTGRES_PASSWORD, 31 | "HOST": POSTGRES_HOST, 32 | "PORT":POSTGRES_PORT 33 | } 34 | } -------------------------------------------------------------------------------- /django-app/cfehome/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for cfehome project. 3 | 4 | Generated by 'django-admin startproject' using Django 3.2. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/3.2/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | 15 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 16 | BASE_DIR = Path(__file__).resolve().parent.parent 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = 'django-insecure-o&(4ribu%e!3it*f20l!&45_&05=rqb@l=+_kir5yle@ueo14f' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = [] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | 'django_celery_beat', 41 | 'django_celery_results', 42 | 'triggers', 43 | ] 44 | 45 | MIDDLEWARE = [ 46 | 'django.middleware.security.SecurityMiddleware', 47 | 'django.contrib.sessions.middleware.SessionMiddleware', 48 | 'django.middleware.common.CommonMiddleware', 49 | 'django.middleware.csrf.CsrfViewMiddleware', 50 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 51 | 'django.contrib.messages.middleware.MessageMiddleware', 52 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 53 | ] 54 | 55 | ROOT_URLCONF = 'cfehome.urls' 56 | 57 | TEMPLATES = [ 58 | { 59 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 60 | 'DIRS': [], 61 | 'APP_DIRS': True, 62 | 'OPTIONS': { 63 | 'context_processors': [ 64 | 'django.template.context_processors.debug', 65 | 'django.template.context_processors.request', 66 | 'django.contrib.auth.context_processors.auth', 67 | 'django.contrib.messages.context_processors.messages', 68 | ], 69 | }, 70 | }, 71 | ] 72 | 73 | WSGI_APPLICATION = 'cfehome.wsgi.application' 74 | 75 | 76 | # Database 77 | # https://docs.djangoproject.com/en/3.2/ref/settings/#databases 78 | 79 | DATABASES = { 80 | 'default': { 81 | 'ENGINE': 'django.db.backends.sqlite3', 82 | 'NAME': BASE_DIR / 'db.sqlite3', 83 | } 84 | } 85 | from .db import * # noqa 86 | 87 | 88 | # Password validation 89 | # https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators 90 | 91 | AUTH_PASSWORD_VALIDATORS = [ 92 | { 93 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 94 | }, 95 | { 96 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 97 | }, 98 | { 99 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 100 | }, 101 | { 102 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 103 | }, 104 | ] 105 | 106 | 107 | # Internationalization 108 | # https://docs.djangoproject.com/en/3.2/topics/i18n/ 109 | 110 | LANGUAGE_CODE = 'en-us' 111 | 112 | TIME_ZONE = 'UTC' 113 | 114 | USE_I18N = True 115 | 116 | USE_L10N = True 117 | 118 | USE_TZ = True 119 | 120 | 121 | # Static files (CSS, JavaScript, Images) 122 | # https://docs.djangoproject.com/en/3.2/howto/static-files/ 123 | 124 | STATIC_URL = '/static/' # http://localhost/static/ 125 | STATIC_ROOT = BASE_DIR / "staticfiles" # collectstatic 126 | 127 | STATICFILES_DIRS = [ 128 | BASE_DIR / "static" 129 | ] 130 | 131 | 132 | # STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles") 133 | # Default primary key field type 134 | # https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field 135 | 136 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' 137 | -------------------------------------------------------------------------------- /django-app/cfehome/urls.py: -------------------------------------------------------------------------------- 1 | """cfehome URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/3.2/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path 18 | 19 | urlpatterns = [ 20 | path('admin/', admin.site.urls), 21 | ] 22 | -------------------------------------------------------------------------------- /django-app/cfehome/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for cfehome project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'cfehome.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /django-app/django: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/Docker-Docker-Compose/665c5c01762ee95546dd9a7902159e530a7932f2/django-app/django -------------------------------------------------------------------------------- /django-app/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import dotenv 5 | import sys 6 | import pathlib 7 | # django-dotenv 8 | 9 | def main(): 10 | USE_DOTENV = os.environ.get("USE_DOTENV_PKG") 11 | if str(USE_DOTENV) == "1": 12 | base_path = pathlib.Path(__file__).resolve().parent 13 | dotenv.read_dotenv(base_path / ".env-dev") 14 | """Run administrative tasks.""" 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'cfehome.settings') 16 | try: 17 | from django.core.management import execute_from_command_line 18 | except ImportError as exc: 19 | raise ImportError( 20 | "Couldn't import Django. Are you sure it's installed and " 21 | "available on your PYTHONPATH environment variable? Did you " 22 | "forget to activate a virtual environment?" 23 | ) from exc 24 | execute_from_command_line(sys.argv) 25 | 26 | 27 | if __name__ == '__main__': 28 | main() 29 | -------------------------------------------------------------------------------- /django-app/requirements.txt: -------------------------------------------------------------------------------- 1 | django>=3.2.0,<3.3.0 2 | django-celery-beat 3 | django-celery-results 4 | celery==5.0.5 5 | django-dotenv 6 | gunicorn 7 | psycopg2-binary 8 | redis -------------------------------------------------------------------------------- /django-app/run-worker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | /usr/local/bin/celery -A cfehome worker --beat -S django -l info -------------------------------------------------------------------------------- /django-app/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | /usr/local/bin/python manage.py migrate --noinput 4 | 5 | /usr/local/bin/python manage.py createsuperuser --noinput 6 | 7 | /usr/local/bin/python manage.py collectstatic --noinput 8 | 9 | RUN_PORT=${PORT:-8000} 10 | /usr/local/bin/gunicorn cfehome.wsgi:application --bind "0.0.0.0:${RUN_PORT}" -------------------------------------------------------------------------------- /django-app/static/css/custom.css: -------------------------------------------------------------------------------- 1 | body { 2 | color:red; 3 | } -------------------------------------------------------------------------------- /django-app/staticfiles/blank-on-purpose.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/Docker-Docker-Compose/665c5c01762ee95546dd9a7902159e530a7932f2/django-app/staticfiles/blank-on-purpose.txt -------------------------------------------------------------------------------- /django-app/todo.md: -------------------------------------------------------------------------------- 1 | - get a prod database -> psql 2 | - run migrate `python manage.py migrate --noinput` 3 | - create a superuser `python manage.py createsuperuser --noinput` 4 | - `DJANGO_SUPERUSER_USERNAME` 5 | - `DJANGO_SUPERUSER_PASSWORD` 6 | - `DJANGO_SUERPUSER_EMAIL` -------------------------------------------------------------------------------- /django-app/triggers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/Docker-Docker-Compose/665c5c01762ee95546dd9a7902159e530a7932f2/django-app/triggers/__init__.py -------------------------------------------------------------------------------- /django-app/triggers/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /django-app/triggers/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class TriggersConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'triggers' 7 | -------------------------------------------------------------------------------- /django-app/triggers/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/Docker-Docker-Compose/665c5c01762ee95546dd9a7902159e530a7932f2/django-app/triggers/migrations/__init__.py -------------------------------------------------------------------------------- /django-app/triggers/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /django-app/triggers/tasks.py: -------------------------------------------------------------------------------- 1 | import time 2 | from celery import shared_task 3 | 4 | @shared_task 5 | def hello_world(num=10): 6 | time.sleep(num) 7 | print(f"Hello world {num}") -------------------------------------------------------------------------------- /django-app/triggers/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /django-app/triggers/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | -------------------------------------------------------------------------------- /docker-compose.dev.yaml: -------------------------------------------------------------------------------- 1 | version: '3.9' 2 | services: 3 | db: 4 | image: postgres 5 | restart: always 6 | env_file: .env-db 7 | ports: 8 | - "5433:5432" 9 | volumes: 10 | - postgres_data:/var/lib/postgresql/data/ 11 | redis: 12 | image: redis 13 | restart: always 14 | ports: 15 | - "6380:6379" 16 | volumes: 17 | - redis_data:/data 18 | entrypoint: redis-server --appendonly yes 19 | 20 | volumes: 21 | redis_data: 22 | postgres_data: -------------------------------------------------------------------------------- /docker-compose.hub.yaml: -------------------------------------------------------------------------------- 1 | version: '3.9' 2 | services: 3 | db: 4 | image: postgres 5 | restart: always 6 | env_file: .env-db 7 | expose: 8 | - 5432 9 | volumes: 10 | - postgres_data:/var/lib/postgresql/data/ 11 | myredis: 12 | image: redis 13 | restart: always 14 | expose: 15 | - 6379 16 | volumes: 17 | - redis_data:/data 18 | entrypoint: redis-server --appendonly yes 19 | thor: 20 | build: 21 | context: ./django-app 22 | dockerfile: Dockerfile.django-app 23 | environment: 24 | - PORT=8001 25 | env_file: 26 | - ./django-app/.env-dj 27 | - ./.env-db 28 | expose: 29 | - 8001 30 | volumes: 31 | - ./staticfiles:/app/staticfiles/ 32 | depends_on: 33 | - db 34 | loki: 35 | build: 36 | context: ./django-app 37 | dockerfile: Dockerfile.django-app 38 | command: ./run-worker.sh 39 | environment: 40 | - REDIS_HOST=myredis 41 | env_file: 42 | - ./django-app/.env-dj 43 | - ./.env-db 44 | volumes: 45 | - ./staticfiles:/app/staticfiles/ 46 | depends_on: 47 | - thor 48 | - db 49 | ironman: 50 | build: 51 | context: ./py-app 52 | dockerfile: Dockerfile.py-app 53 | environment: 54 | - PORT=8081 55 | volumes: 56 | - ./data:/app/data 57 | - mydatavol:/app/mydatavol 58 | expose: 59 | - 8081 60 | depends_on: 61 | - db 62 | falcon: 63 | build: 64 | context: ./express-app 65 | dockerfile: Dockerfile.express-app 66 | environment: 67 | - PORT=8082 68 | volumes: 69 | - ./data:/app/data 70 | expose: 71 | - 8082 72 | zemo: 73 | build: 74 | context: ./php-app 75 | dockerfile: Dockerfile.php-app 76 | environment: 77 | - PORT=8083 78 | expose: 79 | - 8083 80 | batman: 81 | image: codingforentrepreneurs/docker-dc-go-app 82 | environment: 83 | - PORT=8084 84 | expose: 85 | - 8084 86 | nginx: 87 | build: 88 | context: ./nginx 89 | dockerfile: Dockerfile.nginx 90 | ports: 91 | - 8080:80 92 | volumes: 93 | - ./staticfiles:/www/static/ 94 | depends_on: 95 | - thor 96 | - ironman 97 | - falcon 98 | - zemo 99 | - batman 100 | 101 | volumes: 102 | redis_data: 103 | postgres_data: 104 | data: 105 | external: true 106 | staticfiles: 107 | external: true 108 | mydatavol: -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3.9' 2 | services: 3 | db: 4 | image: postgres 5 | restart: always 6 | env_file: .env-db 7 | expose: 8 | - 5432 9 | volumes: 10 | - postgres_data:/var/lib/postgresql/data/ 11 | myredis: 12 | image: redis 13 | restart: always 14 | expose: 15 | - 6379 16 | volumes: 17 | - redis_data:/data 18 | entrypoint: redis-server --appendonly yes 19 | thor: 20 | build: 21 | context: ./django-app 22 | dockerfile: Dockerfile.django-app 23 | environment: 24 | - PORT=8001 25 | env_file: 26 | - ./django-app/.env-dj 27 | - ./.env-db 28 | expose: 29 | - 8001 30 | volumes: 31 | - ./staticfiles:/app/staticfiles/ 32 | depends_on: 33 | - db 34 | loki: 35 | build: 36 | context: ./django-app 37 | dockerfile: Dockerfile.django-app 38 | command: ./run-worker.sh 39 | environment: 40 | - REDIS_HOST=myredis 41 | env_file: 42 | - ./django-app/.env-dj 43 | - ./.env-db 44 | volumes: 45 | - ./staticfiles:/app/staticfiles/ 46 | depends_on: 47 | - thor 48 | - db 49 | ironman: 50 | build: 51 | context: ./py-app 52 | dockerfile: Dockerfile.py-app 53 | environment: 54 | - PORT=8081 55 | volumes: 56 | - ./data:/app/data 57 | - mydatavol:/app/mydatavol 58 | expose: 59 | - 8081 60 | depends_on: 61 | - db 62 | falcon: 63 | build: 64 | context: ./express-app 65 | dockerfile: Dockerfile.express-app 66 | environment: 67 | - PORT=8082 68 | volumes: 69 | - ./data:/app/data 70 | expose: 71 | - 8082 72 | zemo: 73 | build: 74 | context: ./php-app 75 | dockerfile: Dockerfile.php-app 76 | environment: 77 | - PORT=8083 78 | expose: 79 | - 8083 80 | batman: 81 | build: 82 | context: ./go-app 83 | dockerfile: Dockerfile.go-app 84 | environment: 85 | - PORT=8084 86 | expose: 87 | - 8084 88 | nginx: 89 | build: 90 | context: ./nginx 91 | dockerfile: Dockerfile.nginx 92 | ports: 93 | - 8080:80 94 | volumes: 95 | - ./staticfiles:/www/static/ 96 | depends_on: 97 | - thor 98 | - ironman 99 | - falcon 100 | - zemo 101 | - batman 102 | 103 | volumes: 104 | redis_data: 105 | postgres_data: 106 | data: 107 | external: true 108 | staticfiles: 109 | external: true 110 | mydatavol: -------------------------------------------------------------------------------- /docker-dc.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": {} 8 | } -------------------------------------------------------------------------------- /express-app/Dockerfile.express-app: -------------------------------------------------------------------------------- 1 | FROM node:lts-slim 2 | 3 | COPY . /app 4 | WORKDIR /app 5 | 6 | # package.json 7 | RUN npm install 8 | 9 | RUN chmod +x run.sh 10 | 11 | # test 12 | ENV PORT=9000 13 | 14 | CMD ["./run.sh"] -------------------------------------------------------------------------------- /express-app/commands.md: -------------------------------------------------------------------------------- 1 | 2 | ``` 3 | docker build -t express-app -f Dockerfile.express-app . 4 | ``` 5 | 6 | ``` 7 | docker run -p 8082:8000 -e PORT=8000 express-app 8 | ``` 9 | 10 | ``` 11 | docker run -it --rm express-app /bin/bash 12 | ``` 13 | 14 | ``` 15 | docker ps 16 | ``` -------------------------------------------------------------------------------- /express-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-app", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "express": "^4.17.1" 6 | } 7 | } -------------------------------------------------------------------------------- /express-app/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | /usr/local/bin/node server.js -------------------------------------------------------------------------------- /express-app/server.js: -------------------------------------------------------------------------------- 1 | const express = require("express") 2 | const app = express() 3 | const port = process.env.PORT || 3000 4 | // function handleIndex (req, res) { 5 | // res.send("Hello world") 6 | // } 7 | 8 | app.get("/", (req, res)=>{ 9 | res.send("Hello World") 10 | }) 11 | 12 | app.get("/world", (req, res)=>{ 13 | res.send("The World") 14 | }) 15 | 16 | 17 | app.listen(port, ()=>{ 18 | console.log(`Listening on http://localhost:${port}`) 19 | }) -------------------------------------------------------------------------------- /go-app/Dockerfile.go-app: -------------------------------------------------------------------------------- 1 | FROM golang:1.16 2 | 3 | COPY . /go/src/app 4 | WORKDIR /go/src/app 5 | 6 | RUN chmod +x run.sh 7 | 8 | CMD ["./run.sh"] -------------------------------------------------------------------------------- /go-app/commands.md: -------------------------------------------------------------------------------- 1 | 2 | ``` 3 | docker build -t go-app -f Dockerfile.go-app . 4 | ``` 5 | 6 | ``` 7 | docker build -t codingforentrepreneurs/docker-dc-go-app -f Dockerfile.go-app . 8 | ``` 9 | 10 | ``` 11 | docker run -p 8084:8000 -e PORT=8000 go-app 12 | ``` 13 | 14 | ``` 15 | docker run -it --rm go-app /bin/bash 16 | ``` 17 | 18 | ``` 19 | docker ps 20 | ``` 21 | 22 | 23 | ``` 24 | docker push codingforentrepreneurs/docker-dc-go-app 25 | ``` -------------------------------------------------------------------------------- /go-app/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RUN_PORT=${PORT-:8030} 4 | 5 | /usr/local/go/bin/go run server.go -------------------------------------------------------------------------------- /go-app/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "net/http" 7 | ) 8 | 9 | func getEnv(key, fallback string) string { 10 | if value, ok := os.LookupEnv(key); ok { 11 | return value 12 | } 13 | return fallback 14 | } 15 | 16 | func main() { 17 | var port string 18 | port = getEnv("PORT", "8012") 19 | http.HandleFunc("/", HelloServer) 20 | fmt.Println("Running from http://localhost:" + port) 21 | http.ListenAndServe(":" + port, nil) 22 | } 23 | 24 | func HelloServer(w http.ResponseWriter, r *http.Request) { 25 | fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:]) 26 | } -------------------------------------------------------------------------------- /nginx/Dockerfile.nginx: -------------------------------------------------------------------------------- 1 | FROM nginx:latest 2 | 3 | COPY . /www/data 4 | COPY ./static.conf /etc/nginx/conf.d/default.conf -------------------------------------------------------------------------------- /nginx/commands.md: -------------------------------------------------------------------------------- 1 | 2 | ``` 3 | docker build -t my-nginx -f Dockerfile.nginx . 4 | ``` 5 | 6 | ``` 7 | docker run -p 8080:80 my-nginx 8 | ``` 9 | 10 | ``` 11 | docker ps 12 | ``` -------------------------------------------------------------------------------- /nginx/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Hello World

5 | 6 | -------------------------------------------------------------------------------- /nginx/static.conf: -------------------------------------------------------------------------------- 1 | upstream thor { 2 | server thor:8001; 3 | } 4 | 5 | upstream ironman { 6 | server ironman:8081; 7 | } 8 | 9 | upstream falcon { 10 | server falcon:8082; 11 | } 12 | 13 | 14 | upstream zemodancing { 15 | server zemo:8083; 16 | } 17 | 18 | upstream gobatman { 19 | server batman:8084; 20 | } 21 | 22 | server { 23 | listen 80; 24 | server_name localhost; 25 | root /www/data/; 26 | 27 | 28 | location / { 29 | proxy_pass http://thor; 30 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 31 | proxy_set_header Host $host; 32 | proxy_redirect off; 33 | } 34 | 35 | location /iron { 36 | proxy_pass http://ironman; 37 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 38 | proxy_set_header Host $host; 39 | proxy_redirect off; 40 | } 41 | 42 | location /world { 43 | proxy_pass http://falcon; 44 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 45 | proxy_set_header Host $host; 46 | proxy_redirect off; 47 | } 48 | 49 | location /super { 50 | proxy_pass http://zemodancing; 51 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 52 | proxy_set_header Host $host; 53 | proxy_redirect off; 54 | } 55 | 56 | location /darkknight { 57 | proxy_pass http://gobatman; 58 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 59 | proxy_set_header Host $host; 60 | proxy_redirect off; 61 | } 62 | 63 | location /static { 64 | autoindex on; 65 | alias /www/static/; 66 | } 67 | 68 | error_page 500 502 503 504 /50x.html; 69 | location = /50x.html { 70 | root /usr/share/nginx/html; 71 | } 72 | } -------------------------------------------------------------------------------- /nginx/world.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

The World

5 | 6 | -------------------------------------------------------------------------------- /php-app/Dockerfile.php-app: -------------------------------------------------------------------------------- 1 | FROM php:8.0.3 2 | 3 | COPY . ./app 4 | WORKDIR /app 5 | 6 | RUN chmod +x run.sh 7 | 8 | CMD ["./run.sh"] -------------------------------------------------------------------------------- /php-app/commands.md: -------------------------------------------------------------------------------- 1 | 2 | ``` 3 | docker build -t php-app -f Dockerfile.php-app . 4 | ``` 5 | 6 | ``` 7 | docker run -p 8083:8001 -e PORT=8001 php-app 8 | ``` 9 | 10 | ``` 11 | docker run -it --rm php-app /bin/bash 12 | ``` 13 | 14 | ``` 15 | docker ps 16 | ``` -------------------------------------------------------------------------------- /php-app/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP Test 4 | 5 | 6 | Hello World

'; ?> 7 | 8 | 9 | -------------------------------------------------------------------------------- /php-app/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RUN_PORT=${PORT-:8020} 4 | 5 | /usr/local/bin/php -S "0.0.0.0:$RUN_PORT" -------------------------------------------------------------------------------- /php-app/super.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | Super Test 4 | 5 | 6 | Zemo is not super

'; ?> 7 | 8 | 9 | -------------------------------------------------------------------------------- /py-app/Dockerfile.py-app: -------------------------------------------------------------------------------- 1 | FROM python:3.9-slim 2 | 3 | COPY . /app 4 | WORKDIR /app 5 | 6 | RUN pip install pip --upgrade 7 | RUN pip install -r requirements.txt 8 | 9 | RUN chmod +x run.sh 10 | 11 | CMD ["./run.sh"] -------------------------------------------------------------------------------- /py-app/commands.md: -------------------------------------------------------------------------------- 1 | 2 | ``` 3 | docker build -t py-app-1 -f Dockerfile.py-app . 4 | ``` 5 | 6 | ``` 7 | docker run -p 8081:8000 py-app-1 8 | ``` 9 | 10 | ``` 11 | docker run -it py-app-1 /bin/bash 12 | ``` 13 | 14 | ``` 15 | docker ps 16 | ``` -------------------------------------------------------------------------------- /py-app/hello.txt: -------------------------------------------------------------------------------- 1 | hello from container -------------------------------------------------------------------------------- /py-app/requirements.txt: -------------------------------------------------------------------------------- 1 | fastapi 2 | uvicorn -------------------------------------------------------------------------------- /py-app/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RUN_PORT=${PORT:-8010} 4 | /usr/local/bin/uvicorn server:app --host 0.0.0.0 --port $RUN_PORT -------------------------------------------------------------------------------- /py-app/server.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | 3 | app = FastAPI() 4 | 5 | @app.get("/") 6 | def read_index(): 7 | return {"hello": "world"} -------------------------------------------------------------------------------- /staticfiles/blank.txt: -------------------------------------------------------------------------------- 1 | blank for github --------------------------------------------------------------------------------