Getting Started with DigitalOcean CLI `doctl` & Django
By Justin

In Try Django 3.2 we cover how to deploy to DigitalOcean App Platform via the console. In this blog post, we're going to cover how to deploy via the command line tool called doctl.
There are a few reasons to learn about the command line tool but the primary one is this: monitoring app changes via git.
As you know, git is an amazing tool that allows us to track changes in code. Should the services our deployed applications use be any different? No, of course not.
When you use the console to manage your apps, tracking down the history of changes is a bit more complex to do -- not to mention time consuming.
Using the doctl tool from DigitalOcean helps simply deployment & tracking of app-level service changes.
1. Register for a DigitalOcean account & get a $100 credit here.
2. Install doctl following this guide from DigitalOcean
If youre on macOS with Homebrew you can:
brew install doctl
Everyone else, install here.
3. Get an API Token at:
4. Initialize API CLient:
Copy your api token from step 3 and run
doctl auth init
5. Create the App Spec File (app.yaml)
Here's the reference docs for the App Specification.
Below does the following:
- Initializes a DigitalOcean managed database
- Creates a python-based service (ie to run our try django project)
- Runs a one-off job (during deployment) for our python-based service.
- Configures app-level environment variables
yaml
name: Try Django 3.2
databases:
- engine: PG
name: db
num_nodes: 1
size: db-s-dev-database
version: "12"
services:
- environment_slug: python
envs:
- key: DATABASE_URL
scope: RUN_TIME
value: ${db.DATABASE_URL}
git:
branch: production-3
repo_clone_url: https://github.com/codingforentrepreneurs/Try-Django-3.2.git
http_port: 8080
instance_count: 1
instance_size_slug: basic-xxs
name: try-django-3-2
routes:
- path: /
run_command: gunicorn --worker-tmp-dir /dev/shm trydjango.wsgi
source_dir: /
jobs:
- environment_slug: python
envs:
- key: DATABASE_URL
scope: RUN_TIME
value: ${db.DATABASE_URL}
git:
branch: production-3
repo_clone_url: https://github.com/codingforentrepreneurs/Try-Django-3.2.git
instance_count: 1
instance_size_slug: basic-xxs
kind: PRE_DEPLOY
name: django-migrate-job
run_command: python manage.py migrate --noinput
source_dir: /
envs:
- key: DISABLE_COLLECTSTATIC
scope: RUN_AND_BUILD_TIME
value: "1"
- key: DEBUG
scope: RUN_AND_BUILD_TIME
value: "0"
- key: DJANGO_ALLOWED_HOST
scope: RUN_AND_BUILD_TIME
value: .ondigitalocean.app
- key: DJANGO_SUPERUSER_EMAIL
scope: RUN_AND_BUILD_TIME
value: [email protected]
- key: DJANGO_SUPERUSER_USERNAME
scope: RUN_AND_BUILD_TIME
value: cfe
- key: DJANGO_SECRET_KEY
scope: RUN_AND_BUILD_TIME
type: SECRET
value: hellosecret
- key: DJANGO_SUPERUSER_PASSWORD
scope: RUN_AND_BUILD_TIME
type: SECRET
value: ThisIsDOCLI_Deploy
- key: POSTGRES_DB
scope: RUN_AND_BUILD_TIME
value: ${db.DATABASE}
- key: POSTGRES_HOST
scope: RUN_AND_BUILD_TIME
value: ${db.HOSTNAME}
- key: POSTGRES_USER
scope: RUN_AND_BUILD_TIME
value: ${db.USERNAME}
- key: POSTGRES_PASSWORD
scope: RUN_AND_BUILD_TIME
value: ${db.PASSWORD}
- key: POSTGRES_PORT
scope: RUN_AND_BUILD_TIME
value: ${db.PORT}
- key: AWS_ACCESS_KEY_ID
scope: RUN_AND_BUILD_TIME
type: SECRET
value: abc123
- key: AWS_SECRET_ACCESS_KEY
scope: RUN_AND_BUILD_TIME
type: SECRET
value: abc1234
- key: AWS_STORAGE_BUCKET_NAME
scope: RUN_AND_BUILD_TIME
value: trydjango3
6. Key Commands:
Create
bash
echo "$(doctl apps create --spec app.yaml --format ID --no-header)" > app-id.txt
I use this command so I can easily reference the created app's ID. You can always run doctl apps create --spec app.yaml if you need.
If you intend to use the exact same setup for many apps, be sure to change the name in app.yaml. from above.
Update
doctl apps update "$(cat app-id.txt)"
This command works because in Create I added the app-id.txt file.
Delete
doctl apps delete "$(cat app-id.txt)" && rm app-id.txt
This command works because in Create I added the app-id.txt file.
I run rm app-id.txt because I no longer need it after the app is deleted.
list
doctl apps list --format "Spec.Name, ID"