Skip to content

Commit 0aecd8e

Browse files
committed
do the platform/m1 bit and flesh out env file chat
1 parent 5b5cf02 commit 0aecd8e

File tree

2 files changed

+69
-17
lines changed

2 files changed

+69
-17
lines changed

chapter_11_ansible.asciidoc

Lines changed: 69 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -523,22 +523,40 @@ false, "AttachStdout": true, "Cmd": ["gunicorn", "--bind", ":8888",
523523
----
524524

525525

526-
TODO: sort out macos M1/arch issues, `docker build --platform linux/amd64` etc.
526+
For completeness, let's also add a step to explicitly build the image locally.
527+
This means we don't have a dependency on having run `docker build` locally.
527528

529+
530+
[role="sourcecode"]
531+
.infra/ansible-provision.yaml (ch11l003)
532+
====
533+
[source,yaml]
528534
----
535+
- name: Install docker
536+
[...]
537+
529538
- name: Build container image locally
530539
community.docker.docker_image:
531540
name: superlists
532541
source: build
533542
state: present
534543
build:
535544
path: ../Dockerfile
536-
platform: linux/amd64
545+
platform: linux/amd64 # <1>
537546
delegate_to: 127.0.0.1
547+
548+
- name: Export container image locally
538549
----
550+
====
539551

552+
<1> Having this step also allows us to work around an issue
553+
with compatility between Apple's new ARM-based chips and
554+
our server's x86/amd64 architecture.
555+
You could also use this `platform:` to cross-build docker images
556+
for a rasbperry pi from a regular PC, or vice-versa.
540557

541-
Looks ok! Let's see if that worked?
558+
559+
In any case, let's see if it works!
542560

543561
[subs="specialcharacters,quotes"]
544562
----
@@ -573,12 +591,28 @@ Ah woops, we need to set those environment variables on the server too.
573591

574592
=== Using an env File to Store Our Environment Variables
575593

576-
We don't want to save secrets like SECRET_KEY into our ansible
577-
config either.
594+
When we run our container manually locally, we can pass in environment variables with the `-e` flag.
595+
But we don't want to hard-code secrets like SECRET_KEY into our ansible files
596+
and commit them to our repo!
597+
598+
Instead, we can use ansible to automate the creation of a secret key,
599+
and then save it to a file on the server, where it will be relatively secure
600+
(better than saving it to version contorl and pushing it to GitHub in any case!)
601+
602+
We can use a so-called "env file" to store environment variables,
603+
which are essentially a list of key-value pairs using shell syntax,
604+
a bit like you'd use with `export`.
578605

579-
* explain env files.
606+
One extra subtlety is that we want to vary the actual contents of the env file,
607+
depending on where we're deploying to.
608+
Each server should get its own unique secret key,
609+
adn we want different config for staging and prod, for example.
580610

581-
* explain jinja2.
611+
So, just as we inject variables into our html templates in Django,
612+
we can use a templating language called "jinja2" to have variables in our env file.
613+
It's a common tool in ansible scripts, and the syntax is very similar to Django's.
614+
615+
Here's what our template for the env file will looks like:
582616

583617
[role="sourcecode"]
584618
.infra/env.j2 (ch11l003)
@@ -588,10 +622,11 @@ config either.
588622
DJANGO_DEBUG_FALSE=1
589623
DJANGO_SECRET_KEY="{{ secret_key }}"
590624
DJANGO_ALLOWED_HOST="{{ host }}"
591-
592625
----
593626
====
594627

628+
And here's how we use it in the provisioning script:
629+
595630

596631
[role="sourcecode"]
597632
.infra/ansible-provision.yaml (ch11l004)
@@ -602,13 +637,13 @@ DJANGO_ALLOWED_HOST="{{ host }}"
602637
[...]
603638
604639
- name: Ensure .env file exists
605-
ansible.builtin.template:
640+
ansible.builtin.template: #<1>
606641
src: env.j2
607642
dest: ~/superlists.env
608-
vars:
609-
host: "{{ inventory_hostname }}"
643+
force: false # do not recreate file if it already exists. <2>
644+
vars: # <3>
645+
host: "{{ inventory_hostname }}" # <4>
610646
secret_key: "{{ lookup('password', '/dev/null length=32 chars=ascii_letters,digits') }}"
611-
force: false # do not recreate file if it already exists.
612647
613648
- name: Run container
614649
community.docker.docker_container:
@@ -620,17 +655,34 @@ DJANGO_ALLOWED_HOST="{{ host }}"
620655
----
621656
====
622657

623-
The `inventory_hostname` variable is the domain name of the server we're running against.
624-
I'm using the `vars` section to rename it to "host", just for convenience.
658+
<1> We use `ansible.builtin.template` to specify the local template file to use (`src`),
659+
and the destination (`dst`) on the server
660+
661+
<2> `force: false` means we will only write the file once.
662+
So after the first time we generate our secret key, it won't change.
663+
664+
<3> The `vars` section defines the variables we'll inject into our template.
665+
666+
<4> We actually use a built-in ansible variable called `inventory_hostname`.
667+
This variable woul actually be available in the template already,
668+
but I'm renaming it for clarity.
669+
670+
671+
.Idempotency
672+
*******************************************************************************
673+
* TODO: explain idempotency
674+
675+
*******************************************************************************
625676

626-
* explain idempotency
677+
NOTE: Using an env file to store secrets is definitely better than committing
678+
it to version control, but it's maybe not the state of the art either.
679+
TODO: mention other secret management tools. vault
627680

628-
* mention other secret management tools. vault??
629681

630682

631683
==== More debugging
632684

633-
forgot ports
685+
forgot ports!
634686

635687
show ssh, curl localhosts maybe.
636688

images/server_error_500.png

59.5 KB
Loading

0 commit comments

Comments
 (0)