Wait on the container's own health, not the host's DNS
The app's health check ran on the target host against the container name, which only resolves inside the Docker network, so the wait could never succeed. Poll the image's HEALTHCHECK instead and fail with a readable message. Also pin site.env to the app user when it exists, and say how to install the provisioning script on the server.
This commit is contained in:
1 parent
c87cd15c8c
commit
bf824cae26
2 files changed
+44
-10
No files matched your search
+17
-3
@@ -30,8 +30,12 @@ to the app repo, a new image, and a redeploy (ADR 0005).
|
|||||||
# 2. First run: a temporary hostname, so the live site keeps serving
|
# 2. First run: a temporary hostname, so the live site keeps serving
|
||||||
ansible-playbook -l monoco -e site=hopsngrains -e tag=2026-09-22 playbook.yml
|
ansible-playbook -l monoco -e site=hopsngrains -e tag=2026-09-22 playbook.yml
|
||||||
|
|
||||||
# 3. The admin needs a password before it can be used
|
# 3. The admin needs a password before it can be used. The script lives in the
|
||||||
ssh monoco scripts/provision-site-env.sh /var/lib/menu-app.hopsngrains.com
|
# app repo and writes site.env through a container running as the app user,
|
||||||
|
# so the SSH user never needs write access to the data root.
|
||||||
|
scp scripts/provision-site-env.sh monoco:/tmp/
|
||||||
|
ssh monoco bash /tmp/provision-site-env.sh /var/lib/menu-app.hopsngrains.com
|
||||||
|
ssh monoco docker restart menu-app.hopsngrains.com
|
||||||
```
|
```
|
||||||
|
|
||||||
The first run creates `/var/lib/menu-app.hopsngrains.com`, starts the container
|
The first run creates `/var/lib/menu-app.hopsngrains.com`, starts the container
|
||||||
@@ -45,7 +49,17 @@ so — the public menu still serves.
|
|||||||
|
|
||||||
## Checking the parallel run
|
## Checking the parallel run
|
||||||
|
|
||||||
From a phone on restaurant wifi, not from the server:
|
`menu-new.hopsngrains.com` needs a DNS A record pointing at the same address as
|
||||||
|
`menu.hopsngrains.com` before this runs: Caddy fetches a certificate for the
|
||||||
|
name, which needs it to resolve publicly.
|
||||||
|
|
||||||
|
Then, from the outside (read-only, exits non-zero on failure):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run check-site -- https://menu-new.hopsngrains.com
|
||||||
|
```
|
||||||
|
|
||||||
|
And from a phone on restaurant wifi, not from the server:
|
||||||
|
|
||||||
- `https://menu-new.hopsngrains.com/` lists the Sections that have a current menu.
|
- `https://menu-new.hopsngrains.com/` lists the Sections that have a current menu.
|
||||||
- A Section page scrolls, the pour line tracks, tapping a page opens it full width.
|
- A Section page scrolls, the pour line tracks, tapping a page opens it full width.
|
||||||
|
|||||||
@@ -53,15 +53,35 @@
|
|||||||
networks:
|
networks:
|
||||||
- name: "{{ docker_network }}"
|
- name: "{{ docker_network }}"
|
||||||
|
|
||||||
- name: Wait for the app to answer
|
- name: Keep site.env readable only by the app user
|
||||||
uri:
|
file:
|
||||||
url: "http://{{ docker_container }}:3000/healthz"
|
path: "{{ app_root }}/site.env"
|
||||||
status_code: 200
|
owner: "{{ app_uid }}"
|
||||||
|
group: "{{ app_gid }}"
|
||||||
|
mode: "0600"
|
||||||
|
when: menu_site_env.stat.exists
|
||||||
|
|
||||||
|
- name: Wait for the app to report healthy
|
||||||
|
# The image's own HEALTHCHECK fetches /healthz inside the container. Polling
|
||||||
|
# that is deliberate: a container name resolves only on the Docker network, so
|
||||||
|
# the host cannot fetch http://{{ docker_container }}:3000/healthz.
|
||||||
|
docker_container_info:
|
||||||
|
name: "{{ docker_container }}"
|
||||||
register: menu_health
|
register: menu_health
|
||||||
retries: 10
|
|
||||||
delay: 2
|
|
||||||
until: menu_health.status == 200
|
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
retries: 20
|
||||||
|
delay: 5
|
||||||
|
until: >-
|
||||||
|
menu_health.container is defined and
|
||||||
|
menu_health.container.State.Health is defined and
|
||||||
|
menu_health.container.State.Health.Status == 'healthy'
|
||||||
|
|
||||||
|
- name: Fail when the app never becomes healthy
|
||||||
|
fail:
|
||||||
|
msg: >-
|
||||||
|
{{ docker_container }} did not report healthy within 100s. Check
|
||||||
|
`docker logs {{ docker_container }}`.
|
||||||
|
when: menu_health.container.State.Health.Status | default('unknown') != 'healthy'
|
||||||
|
|
||||||
- name: Check the data directory for integrity problems
|
- name: Check the data directory for integrity problems
|
||||||
# Reads the same directory the container writes, as the same user, so a
|
# Reads the same directory the container writes, as the same user, so a
|
||||||
|
|||||||
Reference in new issue
Block a user