├── .devcontainer ├── compose.yaml └── devcontainer.json ├── .dockerignore ├── .github └── workflows │ └── docker-image.yml ├── .gitignore ├── .vscode └── launch.json ├── Dockerfile ├── Dockerfile.frontend ├── Makefile ├── README.md ├── compose.linux.yaml ├── compose.yaml ├── setup-db.sh ├── setup.sh └── update.sh /.devcontainer/compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | web: 3 | volumes: 4 | - ./.vscode:/code/.vscode:delegated,rw 5 | 6 | # Overrides default command so things don't shut down after the process ends. 7 | command: /bin/sh -c "while sleep 1000; do :; done" 8 | -------------------------------------------------------------------------------- /.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.163.1/containers/docker-existing-docker-compose 3 | // If you want to run as a non-root user in the container, see .devcontainer/compose.yaml. 4 | { 5 | "name": "Existing Docker Compose (Extend)", 6 | "dockerComposeFile": [ 7 | "../compose.yaml", 8 | "compose.yaml" 9 | ], 10 | "service": "web", 11 | "workspaceFolder": "/code", 12 | "settings": { 13 | "terminal.integrated.shell.linux": "bash", 14 | "python.pythonPath": "/usr/local/bin/python" 15 | }, 16 | "extensions": [ 17 | "ms-python.python", 18 | "editorconfig.editorconfig" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # Don't copy the git repos, the compiled node_modules, or anything else that isn't needed into the docker image. 2 | # This greatly speeds up re-building the image. 3 | **/.git 4 | **/node_modules 5 | **/Dockerfile 6 | **/docker-compose.yml 7 | **/compose.yaml 8 | **/Procfile 9 | **/Vagrantfile 10 | **/.devcontainer 11 | **/.vscode 12 | -------------------------------------------------------------------------------- /.github/workflows/docker-image.yml: -------------------------------------------------------------------------------- 1 | name: Docker Image CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Build the Docker image 18 | run: | 19 | ./setup.sh 20 | docker build . --file Dockerfile --tag docker-wagtail-develop:$(date +%s) 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | wagtail 2 | bakerydemo 3 | libs 4 | .idea 5 | .vscode 6 | .DS_Store 7 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 3 | "version": "0.2.0", 4 | "configurations": [ 5 | { 6 | "name": "Python: Django", 7 | "type": "python", 8 | "request": "launch", 9 | "program": "${workspaceFolder}/bakerydemo/manage.py", 10 | "args": ["runserver", "0.0.0.0:8000"], 11 | "django": true, 12 | "justMyCode": false, 13 | "cwd": "${workspaceFolder}/bakerydemo/" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Use an official Python runtime as a parent image 2 | FROM python:3.12-bullseye 3 | LABEL maintainer="hello@wagtail.org" 4 | 5 | # Set environment varibles 6 | ENV PYTHONUNBUFFERED 1 7 | 8 | # Install libenchant and create the requirements folder. 9 | RUN apt-get update -y \ 10 | && apt-get install -y libenchant-2-dev postgresql-client \ 11 | && mkdir -p /code/requirements 12 | 13 | # Install the bakerydemo project's dependencies into the image. 14 | COPY ./bakerydemo/requirements/* /code/requirements/ 15 | RUN pip install --upgrade pip \ 16 | && pip install -r /code/requirements/production.txt 17 | 18 | # Install wagtail from the host. This folder will be overwritten by a volume mount during run time (so that code 19 | # changes show up immediately), but it also needs to be copied into the image now so that wagtail can be pip install'd. 20 | COPY ./wagtail /code/wagtail/ 21 | RUN cd /code/wagtail/ \ 22 | && pip install -e .[testing,docs] 23 | 24 | # Install Willow from the host. This folder will be overwritten by a volume mount during run time (so that code 25 | # changes show up immediately), but it also needs to be copied into the image now so that Willow can be pip install'd. 26 | COPY ./libs/Willow /code/willow/ 27 | RUN cd /code/willow/ \ 28 | && pip install -e .[testing] 29 | -------------------------------------------------------------------------------- /Dockerfile.frontend: -------------------------------------------------------------------------------- 1 | FROM node:22-slim 2 | LABEL maintainer="hello@wagtail.org" 3 | 4 | RUN apt-get update && apt-get install rsync make -y 5 | COPY ./wagtail/package.json ./wagtail/package-lock.json ./ 6 | 7 | RUN npm --prefix / install --loglevel info 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: help 2 | .DEFAULT_GOAL := help 3 | 4 | help: ## ⁉️ - Display help comments for each make command 5 | @grep -E '^[0-9a-zA-Z_-]+:.*? .*$$' \ 6 | $(MAKEFILE_LIST) \ 7 | | awk 'BEGIN { FS=":.*?## " }; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' \ 8 | | sort 9 | 10 | build: ## Build the backend Docker image 11 | docker compose build web 12 | 13 | start: ## Bring the backend Docker container up 14 | docker compose up web 15 | 16 | stop: ## Stop the backend Docker container 17 | docker compose stop 18 | 19 | ssh: ## Enter the running backend Docker container for the wagtail bakery site 20 | docker compose exec web bash 21 | 22 | ssh-shell: ## Enter the running Docker container shell 23 | docker compose exec web python manage.py shell 24 | 25 | ssh-fe: ## Open a shell to work with the frontend code (Node/NPM) 26 | docker compose exec frontend bash 27 | 28 | ssh-wagtail: ## Enter the running Docker container for the wagtail development environment 29 | docker compose exec -w /code/wagtail web bash 30 | 31 | ssh-db: ## Open a PostgreSQL shell session 32 | docker compose exec web python manage.py dbshell 33 | 34 | destroy-db: ## Remove the volume containing the PostgreSQL data 35 | docker volume rm docker-wagtail-develop_postgres-data 36 | 37 | down: ## Stop and remove all Docker containers 38 | docker compose down 39 | 40 | migrations: ## Make migrations to the wagtail bakery site 41 | docker compose exec web python manage.py makemigrations 42 | 43 | migrate: ## Migrate the wagtail bakery site migrations 44 | docker compose exec web python manage.py migrate 45 | 46 | test: ## Run all wagtail tests or pass in a file with `make test file=wagtail.admin.tests.test_name` 47 | docker compose exec -w /code/wagtail web python runtests.py $(file) $(FILE) 48 | 49 | format-wagtail: ## Format Wagtail repo 50 | docker compose exec -w /code/wagtail web make format-server 51 | docker compose exec frontend make format-client 52 | 53 | lint-wagtail: ## Lint the Wagtail repo (server, client, docs) 54 | docker compose exec -w /code/wagtail web make lint-server 55 | docker compose exec -w /code/wagtail web make lint-docs 56 | docker compose exec frontend make lint-client 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # docker-wagtail-develop 2 | 3 | A script to painlessly set up a Docker environment for development of Wagtail - inspired by [vagrant-wagtail-develop](https://github.com/wagtail/vagrant-wagtail-develop) 4 | 5 | Initial work in Bristol sprint January 2020 by [esperk](https://github.com/esperk) and [saevarom](https://github.com/saevarom). 6 | 7 | ## Setup 8 | 9 | **Requirements:** [Docker](https://www.docker.com/) and Docker Compose (Docker Compose is included with Docker Desktop for Mac and Windows). 10 | 11 | Open a terminal and follow those instructions: 12 | 13 | ```sh 14 | # 1. Decide where to put the project. We use "~/Development" in our examples. 15 | cd ~/Development 16 | # 2. Clone the docker-wagtail-develop repository in a new "wagtail-dev" folder. 17 | git clone https://github.com/wagtail/docker-wagtail-develop.git wagtail-dev 18 | # 3. Move inside the new folder. 19 | cd wagtail-dev/ 20 | # 4. Run the setup script. This will check out the bakerydemo project and local copies of wagtail and its dependencies. 21 | ./setup.sh 22 | # 5. Build the containers 23 | docker compose build 24 | ``` 25 | 26 | It can take a while (typically 15-20 minutes) to fetch and build all dependencies and containers. 27 | 28 | Here is the resulting folder structure: 29 | 30 | ```sh 31 | . 32 | ├── libs # Supporting libraries to develop Wagtail against. 33 | ├── wagtail # Wagtail repository / codebase. 34 | └── bakerydemo # Wagtail Bakery project used for development. 35 | ``` 36 | 37 | Once the build is complete: 38 | 39 | ```sh 40 | # 6. Start your containers and wait for them to finish their startup scripts. 41 | docker compose up web 42 | ``` 43 | 44 | You might see a message like this the first time you run your containers. This is normal because the frontend container has not finished building the assets for the Wagtail admin. Just wait a few seconds for the frontend container to finish building (you should see a message like `webpack compiled successfully in 15557 ms` and then stop and start your containers again (Ctrl+C + `docker compose up`). 45 | 46 | ```` 47 | WARNINGS: 48 | ?: (wagtailadmin.W001) CSS for the Wagtail admin is missing 49 | HINT: 50 | Most likely you are running a development (non-packaged) copy of 51 | Wagtail and have not built the static assets - 52 | see https://docs.wagtail.org/en/latest/contributing/developing.html 53 | 54 | File not found: /code/wagtail/wagtail/admin/static/wagtailadmin/css/normalize.css``` 55 | 56 | ```` 57 | 58 | ```sh 59 | # 7. Now in a new shell, run the database setup script. The database will be persisted across container executions by Docker's Volumes system so you will only need to run this command the first time you start the database. 60 | ./setup-db.sh 61 | # Success! 62 | ``` 63 | 64 | If you're running this on Linux you might get into some privilege issues that can be solved using this command (tested on Ubuntu): 65 | 66 | ```sh 67 | CURRENT_UID=$(id -u):$(id -g) docker compose -f compose.yaml -f compose.linux.yaml up 68 | ``` 69 | 70 | Alternatively, if you're using VSCode and have the "Remote - Containers" extension, you can open the command palette and select "Remote Containers - Reopen in Container" to attach VSCode to the container. This allows for much deeper debugging. 71 | 72 | - Visit your site at http://localhost:8000 73 | - The admin interface is at http://localhost:8000/admin/ - log in with `admin` / `changeme`. 74 | 75 | ## What you can do 76 | 77 | ### See a list of running containers 78 | 79 | ```sh 80 | $ docker compose ps 81 | Name Command State Ports 82 | -------------------------------------------------------------------------- 83 | db docker-entrypoint.sh postgres Up 5432/tcp 84 | frontend docker-entrypoint.sh /bin/ ... Up 85 | web ./manage.py runserver 0.0. ... Up 0.0.0.0:8000->8000/tcp 86 | ``` 87 | 88 | ### Build the backend Docker image 89 | 90 | ```sh 91 | make build 92 | ``` 93 | 94 | or 95 | 96 | ```sh 97 | docker compose build web 98 | ``` 99 | 100 | ### Bring the backend Docker container up 101 | 102 | ```sh 103 | make start 104 | ``` 105 | 106 | or 107 | 108 | ```sh 109 | docker compose up 110 | ``` 111 | 112 | ### Stop all Docker containers 113 | 114 | ```sh 115 | make stop 116 | ``` 117 | 118 | or 119 | 120 | ```sh 121 | docker compose stop 122 | ``` 123 | 124 | ### Stop all and remove all Docker containers 125 | 126 | ```sh 127 | make down 128 | ``` 129 | 130 | or 131 | 132 | ```sh 133 | docker compose down 134 | ``` 135 | 136 | ### Run tests 137 | 138 | ```sh 139 | make test 140 | ``` 141 | 142 | or 143 | 144 | ```sh 145 | docker compose exec -w /code/wagtail web python runtests.py 146 | ``` 147 | 148 | ### Run tests for a specific file 149 | 150 | ```sh 151 | make test file=wagtail.admin.tests.test_name 152 | ``` 153 | 154 | or 155 | 156 | ```sh 157 | docker compose exec -w /code/wagtail web python runtests.py wagtail.admin.tests.{test_file_name_here} 158 | ``` 159 | 160 | ### Format Wagtail codebase 161 | 162 | ```sh 163 | make format-wagtail 164 | ``` 165 | or 166 | ```sh 167 | docker compose exec -w /code/wagtail web make format-server 168 | docker compose exec frontend make format-client 169 | ``` 170 | 171 | ### Lint Wagtail codebase 172 | 173 | ```sh 174 | make lint-wagtail 175 | ``` 176 | or 177 | ```sh 178 | docker compose exec -w /code/wagtail web make lint-server 179 | docker compose exec -w /code/wagtail web make lint-docs 180 | docker compose exec frontend make lint-client 181 | ``` 182 | 183 | ### Open a Django shell session 184 | 185 | ```sh 186 | make ssh-shell 187 | ``` 188 | 189 | or 190 | 191 | ```sh 192 | docker compose exec web python manage.py shell 193 | ``` 194 | 195 | ### Open a PostgreSQL shell session 196 | 197 | ```sh 198 | make ssh-db 199 | ``` 200 | 201 | or 202 | 203 | ```sh 204 | docker compose exec web python manage.py dbshell 205 | ``` 206 | 207 | ### Open a shell on the web server 208 | 209 | ```sh 210 | make ssh 211 | ``` 212 | 213 | or 214 | 215 | ```sh 216 | docker compose exec web bash 217 | ``` 218 | 219 | ### Open a shell to work with the frontend code (Node/NPM) 220 | 221 | ```sh 222 | make ssh-fe 223 | ``` 224 | 225 | or 226 | 227 | ```sh 228 | docker compose exec frontend bash 229 | ``` 230 | 231 | ### Open a shell to work within the wagtail container 232 | 233 | ```sh 234 | make ssh-fe 235 | ``` 236 | 237 | or 238 | 239 | ```sh 240 | docker compose exec -w /code/wagtail web bash 241 | ``` 242 | 243 | ### Make migrations to the wagtail bakery site 244 | 245 | ```sh 246 | make migrations 247 | ``` 248 | 249 | or 250 | 251 | ```sh 252 | docker compose exec web python manage.py makemigrations 253 | ``` 254 | 255 | ### Migrate the wagtail bakery site 256 | 257 | ```sh 258 | make migrate 259 | ``` 260 | 261 | or 262 | 263 | ```sh 264 | docker compose exec web python manage.py migrate 265 | ``` 266 | 267 | ### Destroy the current database volume 268 | 269 | If this project has changed database versions since you first started using it, you may need to 270 | delete the database volume and then recreate the bakerydemo data using the `setup-db.sh script`. To 271 | delete all the data from the database running in the `db` container, run the following commands: 272 | 273 | ```sh 274 | make down 275 | make destroy-db 276 | ``` 277 | 278 | or 279 | 280 | ```sh 281 | docker compose down 282 | docker volume rm docker-wagtail-develop_postgres-data 283 | ``` 284 | 285 | ## Getting ready to contribute 286 | 287 | Here are other actions you will likely need to do to make your first contribution to Wagtail. 288 | 289 | Set up git remotes to Wagtail forks (run these lines outside of the Docker instances, on your machine): 290 | 291 | ```sh 292 | cd ~/Development/wagtail-dev/wagtail 293 | # Change the default origin remote to point to your fork. 294 | git remote set-url origin git@github.com:/wagtail.git 295 | # Add wagtail/wagtail as the "upstream" remote. 296 | git remote add upstream git@github.com:wagtail/wagtail.git 297 | # Pull latest changes from all remotes / forks. 298 | git pull --all 299 | ``` 300 | 301 | ## Contributing to Willow 302 | 303 | You can use the same setup to contribute to Willow. 304 | You simply do the same operations to fork the Willow project and point your local copy of Willow to your fork. 305 | 306 | ## See also 307 | 308 | - [Vagrant Wagtail development](https://github.com/wagtail/vagrant-wagtail-develop) 309 | 310 | ## Testing with Elasticsearch 311 | 312 | To test the Wagtail search with the [Elasticsearch backend](https://docs.wagtail.org/en/stable/topics/search/backends.html#elasticsearch-backend) or OpenSearch, use the additional service: 313 | 314 | ```sh 315 | docker compose up web elastic 316 | ``` 317 | 318 | Then install any dependencies and configure Wagtail per the developer documentation, configuring the search backend to use `http://elastic:9200` as the URL. 319 | -------------------------------------------------------------------------------- /compose.linux.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | frontend: 5 | user: ${CURRENT_UID} 6 | 7 | -------------------------------------------------------------------------------- /compose.yaml: -------------------------------------------------------------------------------- 1 | volumes: 2 | postgres-data: 3 | node_modules: 4 | 5 | services: 6 | web: 7 | container_name: "web" 8 | build: ./ 9 | working_dir: /code/bakerydemo 10 | command: python manage.py runserver 0.0.0.0:8000 11 | restart: "no" 12 | volumes: 13 | - ./wagtail:/code/wagtail:delegated,rw 14 | - ./bakerydemo:/code/bakerydemo:delegated,rw 15 | - node_modules:/code/wagtail/node_modules/ 16 | ports: 17 | - "8000:8000" 18 | environment: 19 | DATABASE_URL: "postgres://wagtail:changeme@db/wagtail" 20 | PYTHONPATH: "/code/wagtail:/code/bakerydemo" 21 | depends_on: 22 | - db 23 | - frontend 24 | 25 | db: 26 | container_name: "db" 27 | image: postgres:14 28 | environment: 29 | POSTGRES_USER: wagtail 30 | POSTGRES_DB: wagtail 31 | POSTGRES_PASSWORD: changeme 32 | volumes: 33 | - postgres-data:/var/lib/postgresql/data 34 | restart: "no" 35 | expose: 36 | - "5432" 37 | 38 | frontend: 39 | container_name: "frontend" 40 | build: 41 | context: . 42 | dockerfile: Dockerfile.frontend 43 | working_dir: /code/wagtail 44 | volumes: 45 | - ./wagtail:/code/wagtail:delegated,rw 46 | - node_modules:/code/wagtail/node_modules/ 47 | command: bash -c "echo 'Copying node_modules, this may take a few minutes...' && rsync -rah --info=progress2 /node_modules /code/wagtail/ && npm run start" 48 | restart: "no" 49 | tty: true 50 | 51 | elastic: 52 | container_name: elastic 53 | image: elasticsearch:8.17.1 54 | ports: 55 | - "9200:9200" 56 | - "9300:9300" 57 | environment: 58 | - xpack.security.enabled=false 59 | - discovery.type=single-node 60 | -------------------------------------------------------------------------------- /setup-db.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Fail if any command fails. 4 | set -e 5 | 6 | docker compose exec web python manage.py migrate --noinput 7 | docker compose exec web python manage.py load_initial_data 8 | docker compose exec web python manage.py update_index 9 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Fail if any command fails. 4 | set -e 5 | 6 | if [ ! -d "bakerydemo" ]; then 7 | git clone https://github.com/wagtail/bakerydemo.git 8 | else 9 | echo Directory bakerydemo already exists, skipping... 10 | fi 11 | 12 | 13 | if [ ! -d "wagtail" ]; then 14 | git clone https://github.com/wagtail/wagtail.git 15 | else 16 | echo Directory wagtail already exists, skipping... 17 | fi 18 | 19 | 20 | mkdir -p libs 21 | 22 | 23 | if [ ! -d "libs/django-modelcluster" ]; then 24 | git clone https://github.com/wagtail/django-modelcluster.git libs/django-modelcluster 25 | else 26 | echo Directory libs/django-modelcluster already exists, skipping... 27 | fi 28 | 29 | 30 | if [ ! -d "libs/Willow" ]; then 31 | git clone https://github.com/wagtail/Willow.git libs/Willow 32 | else 33 | echo Directory libs/Willow already exists, skipping... 34 | fi 35 | 36 | 37 | # Set up bakerydemo to use the Postgres database in the sister container 38 | if [ ! -f bakerydemo/bakerydemo/settings/local.py ]; then 39 | echo "Creating local settings file" 40 | cp bakerydemo/bakerydemo/settings/local.py.example bakerydemo/bakerydemo/settings/local.py 41 | fi 42 | 43 | # Create a blank .env file in bakerydemo to keep its settings files from complaining 44 | if [ ! -f bakerydemo/.env ]; then 45 | echo "Creating file for local environment variables" 46 | echo "DJANGO_SETTINGS_MODULE=bakerydemo.settings.dev" > bakerydemo/.env 47 | fi 48 | -------------------------------------------------------------------------------- /update.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | CURRENT_DIR=$PWD 6 | 7 | echo "Updating bakerydemo" 8 | cd $CURRENT_DIR/bakerydemo && git pull --rebase 9 | 10 | echo "Updating wagtail" 11 | cd $CURRENT_DIR/wagtail && git pull --rebase 12 | 13 | echo "Updating django-modelcluster" 14 | cd $CURRENT_DIR/libs/django-modelcluster && git pull --rebase 15 | 16 | echo "Updating Willow" 17 | cd $CURRENT_DIR/libs/Willow && git pull --rebase 18 | --------------------------------------------------------------------------------