This is a guide to the tools and workflows that you'll need to use when changing and updating YNR on your development machine.
Install and test the development prerequisites as detailed in INSTALL.md. This will leave you with a known-good setup that's able to run the commands described in this guide.
If you have access to a database dump from a YNR instance you can restore it to a containerised database as follows:
- Start the database container:
podman compose up -d dbpsql
- Restore the database dump:
cat path/to/database.dump \ | podman compose exec -T dbpsql pg_restore -d ynr -U ynr --no-owner
- Apply any pending migrations:
./scripts/container.run.bash python manage.py migrate
- Shut down the database container:
podman compose down
- Add or update any environment variables in
env/frontend.env
as required. - Incorporate the settings from
ynr/settings/local.py.container.example
into your gitignoredynr/settings/local.py
file. - Start the compose stack:
podman compose up -d
- (In a separate terminal) Start tailing the stack's logs:
podman compose logs --follow
(you can safely CTRL-C this process at any time). - (If your active
ynr/settings/...
file does NOT includeDEBUG = True
)
Collect the static assets:./scripts/container.manage-py.bash collectstatic --no-input
- Browse to http://localhost:8080
- Changes made inside
ynr/
will be immediately available to the app, which will be auto-reloaded. - Remember to shut down the compose stack when you're done:
podman compose down
- Start the compose stack:
podman compose up -d
- Run the test suite:
./scripts/container.pytest.bash
- We can provide additional pytest options.
For example, to run the test suite and stop on the first failure:
./scripts/container.pytest.bash -x
- We can provide additional pytest options.
For example, to run the test suite and stop on the first failure:
- Stop the compose stack:
podman compose down
- Start the compose stack's database server:
podman compose up -d dbpsql
- Run the entire test suite in a new container (without starting the app):
./scripts/container.run.bash pytest
- Stop the compose stack:
podman compose down
As detailed later in this guide, there are several different ways
to run a command inside a frontend container.
The method described here uses a
dedicated script to invoke a Django management command inside a frontend
container that's already running the webapp.
(If you need to run a command but don't want to start the webapp, use the more
general container.run.bash
script instead).
Run a Django management command:
- Add or update any environment variables in
env/frontend.env
as required. - Start the compose stack:
podman compose up -d
- Use the
container.manage-py.bash
script to invoke the command:# ./scripts/container.manage-py.bash command-to-invoke --command-args command params # e.g. ./scripts/container.manage-py.bash check
- Stop the compose stack:
podman compose down
After you stop the compose stack, any files added or changed by the management
command inside the ynr
directory will be persisted directly on your machine.
The same applies to any files mentioned in
docker-compose.yml
,
in the frontend
container's "volumes
" section.
Any changes the management command makes to files outside those locations
will be lost when you stop the compose stack.
Changes to the database are persisted in the database's data volume.
YNR uses a container runtime called Podman. You can think
of it as like Docker, but able to run without needing a persistent background
daemon and without requiring root access.
Podman provides the podman
command which is intended to be CLI-compatible
with much of the docker
command.
You've also been asked to install podman-compose
- a separate project that
gives the podman
command its podman compose
subcommand. You shouldn't need
to invoke podman-compose
(with a hyphen) directly. The podman compose
command works with the "compose stack" defined in
docker-compose.yml, which comprises two services: the
frontend
webapp, and the Postgres dbpsql
service.
Use podman compose up -d
to start the compose stack, with the webapp exposed
on localhost:8080. Changes you make inside the ynr/
directory are automatically reflected in the running app. Changes to other
entries in the frontend's docker-compose.yml list of
volumes that are bind-mounted from your local checkout of this repo are also
immediately visible to the running app.
View the app (and DB) logs with podman compose logs --follow
. It's a good
idea to run this immediately after starting the stack.
Shut down the stack with podman compose down
. This is always safe to run,
even when the stack is already stopped. It deliberately leaves the database's
data behind as a "volume", so that Postgres can access it the next time you
start the stack. If you need to delete the database's contents completely, run
podman compose down --volumes
.
podman compose ...
subcommands do provide the expected --help
flag, but
some of the docs aren't perfect. Here's a summary of the commands you might
run:
Command | Purpose | Notes |
---|---|---|
podman compose up -d |
Start the entire stack. | -d forks the action into the background, which is optional but strongly recommended. |
podman compose up -d dbpsql |
Start only the named container in the stack. | |
podman compose down |
Stop any running containers in the stack. | |
podman compose down --volumes |
Stop any running containers in the stack and also destroy their persistent data. | Anything bind-mounted from your local repo into the frontend webapp container is left untouched. |
podman compose ps |
Display the status of containers in the stack. | |
podman volume ls |
List the persistent volumes that podman controls on your machine. | |
podman compose build |
Rebuild the webapp's frontend container image. | |
podman compose build --no-cache |
Rebuild the webapp's frontend container image from scratch. | Takes several minutes to finish. |
podman compose logs |
Display the last N stdout/stderr lines emitted by any running containers. | |
podman compose logs --follow |
Display the last N stdout/stderr lines emitted by any running containers, and then wait for more lines. | |
podman system reset |
Destroy everything that Podman controls. | "Everything seems to have gone wrong, so I'll just start from scratch". It wipes out all containers, networks, images, volumes, etc ... so avoid this if possible! |
These executable scripts are available from the scripts
directory.
Script | Purpose | Parameters |
---|---|---|
container.image.build.bash |
Builds the YNR container image | $1 -- The named stage from container/build/Containerfile to build and tag (required)$2, $3, ... -- Any parameters to pass to the underlying builder process (optional) |
container.exec.bash |
Runs a command inside the already-running frontend container |
The unquoted command to run (required) |
container.manage-py.bash |
Runs a Django management command inside the already-running frontend container |
The unquoted command to run (required) |
container.pytest.bash |
Runs pytest inside the already-running frontend container |
Any parameters for Pytest (optional) |
container.run.bash |
Runs a command inside a freshly-instantiated, ephemeral frontend container |
The unquoted command to run (required) |
You will need to rebuild the application's container image if you change any of the application's dependencies, across any of the packaging ecosystems it currently relies on:
container/build/system-packages
: System / APT dependendenciespackage{,-lock}.json
: Node dependenciesrequirements/*.txt
: Python dependencies.dockerignore
: Container build-time file dependencies
The above list is presented in descending order of how slow a rebuild will be,
if a particular package ecosystem's dependencies are changed.
Changing a system dependency, for example, forces a longer rebuild than
changing a Python dependency.
You do not need to rebuild the application's container image if you only
change files in the ynr/
directory. Changes to the YNR application are
picked up automatically when using the compose stack locally (as described
elsewhere in this guide).
The build process for the YNR application is encoded in
container/build/Containerfile
.
This Docker-compatible file describes two image stages, prod
and test
, with
test
being built on top of prod
.
Locally, on your development machine, you will need to use the test
stage.
./scripts/container.image.build.bash test
Avoiding the use of your local build cache significantly increases the time it takes to build the container image, but is sometimes useful when there's a problem with external dependencies (e.g. if a important update has been published for an APT package but it's not visible in the container's package index).
./scripts/container.image.build.bash test --no-cache