Developing Discourse using a Dev Container

Dev Containers is an open standard for configuring a development environment inside a container. This almost entirely eliminates the need to install/configure Discourse-specific tools/dependencies on your local machine, and makes it very easy to keep up-to-date as Discourse evolves over time.

Dev Containers can be used in a number of different IDEs, or directly using their reference CLI. This guide will describe the setup process for VSCode.

Getting started

  1. Download and install VSCode

  2. Install the Dev Containers extension in VSCode

  3. Clone the Discourse repository onto your machine

    git clone https://github.com/discourse/discourse
    
  4. In VSCode, use FileOpen Folder, then choose the Discourse directory

  5. Open the folder in its Dev Container. This can be done via the popup prompt, or by opening the command palette (Cmd/Ctrl + Shift + P) and searching for “Open folder in container…”

  6. If this is your first time launching a container, you will be prompted to install and start Docker Desktop. Once complete, go back to VSCode re-run “Open folder in container…”

  7. Wait for the container to download and start. When it’s done, the README will appear, and you’ll see the Discourse filesystem in the sidebar.

  8. Run the default build task using Cmd/Ctrl + Shift + B.

    This will install dependencies, migrate the database, and start the server. It’ll take a few minutes, especially on the lower-end machines. You’ll see “Build successful” in the terminal when it’s done.

  9. Run the dev/admin/create task. Open the command palette and search for “Tasks: Run Tasks”. It will present a menu of tasks; select dev/admin/create off of that list. You’ll be prompted to enter an email address and a password for your admin user.

  10. Visit http://localhost:3000 in your browser to see your new Discourse instance

  11. All done! You can now make changes to Discourse’s source code and see them reflected in the preview.

Running tests

The first time you run tests, you’ll need to install testing dependencies, including Playwright and the discourse_test DB. You can run the deps/testing task to install those. Open the command palette, select “Tasks: Run Tasks”. It will present a menu of tasks; select deps/testing off of that list.

Once the test dependencies are installed, you can run bin/lint, bin/qunit, or the system specs

Applying config/container updates

Every so often, the devcontainer config and the associated container image will be updated. VSCode should prompt you to “rebuild” to apply the changes. Alternatively, you can run “Dev Containers: Rebuild Container” from the VSCode command palette. The working directory, and your Redis/Postgres data will be preserved across rebuilds.

If you’d like to start from scratch with fresh database, you’ll need to delete the discourse-pg and discourse-redis docker volumes. This can be done from the “Remote Explorer” tab of the VSCode sidebar.

Discourse’s sample vscode .vscode/settings.json and .vscode/tasks.json will be copied when you first boot the codespace. From that point forward, if you want to use the latest sample config, you’ll need to manually copy .vscode/settings.json.sample to .vscode/settings.json.

References


This document is version controlled - suggest changes on github.

14개의 좋아요

Hi,

No admin account created

When using the docker container from outside via the scripts in d/ (e.g. d/boot_dev --init as specified in Install Discourse for development using Docker , it asks me to set up an admin account as part of the process.

However, when using it as a Dev Container and running the build steps (ctrl/cmd + shift + b) it does NOT create an admin.

From glancing at the instructions, I first had the impression that creating an admin is quite arduous; but then I realized that all it takes is this command, leaving it here for those who run into the same issue:

rake admin:create

(or, if it complains about a different rake version required: bundle exec rake admin:create)

7개의 좋아요

On Windows 11, if you don’t want to run into line ending issues, such as:

[23963 ms] Start: Run in container: /bin/sh -c ./.devcontainer/scripts/start.rb
/usr/bin/env: ‘ruby\r’: No such file or directory
/usr/bin/env: use -[v]S to pass options in shebang lines

.. make sure to Clone in Volume

6개의 좋아요

Maybe there is a better way, but to work on plugins I have a discourse-plugins sibling folder alongside my main discourse repo folder. This mounts to /workspace/plugins so I can then create symlinks within the container.

This is what I added to mounts in devcontainer.json:
"source=${localWorkspaceFolder}/../${localWorkspaceFolderBasename}-plugins,target=/workspace/plugins,type=bind"

2개의 좋아요

This is indeed useful, thank you.

1개의 좋아요

… Or just git reset --hard
Worked for me
Then Dev Container: Rebuild Container and Ctrl-Shift-B

If you are using OrbStack (not affiliated) on your local macOS environment, and want to run Discourse on HTTPS with a custom domain, update your devcontainer.json with following additions:

  1. Give a name to the container.
  2. Add .orb.local wildcard domain to RAILS_DEVELOPMENT_HOSTS environment variable (hostnames must be separated by a comma).
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -13,10 +13,11 @@
   ],
   "remoteUser": "discourse",
   "remoteEnv": {
-    "RAILS_DEVELOPMENT_HOSTS": ".app.github.dev",
+    "RAILS_DEVELOPMENT_HOSTS": ".app.github.dev,.orb.local", // Step 2
     "PGUSER": "discourse",
     "SELENIUM_FORWARD_DEVTOOLS_TO_PORT": "9229",
   },
+  "runArgs": ["--name","discourse"], // Step 1
   "mounts": [
     "source=${localWorkspaceFolderBasename}-node_modules,target=${containerWorkspaceFolder}/node_modules,type=volume",
     "source=${localWorkspaceFolderBasename}-pg,target=/shared/postgres_data,type=volume",

p.s. please let me know, if you know how I can set the *.orb.local hostname and the container name dynamically, as it is defined for GitHub Codespaces. Setting the value as .app.github.dev,.orb.local didn’t work for me.

Update: Somehow, I was missing a record in my /etc/hosts file. After adding this line, I was able to use .orb.local wildcard domain in step 2.

With these changes in the devcontainer.json file, now I can run my local Discourse instance at https://discourse.orb.local/

/etc/hosts

Add this line to your /etc/hosts file if you don’t already have it.

##
# Docker and OrbStack
##
127.0.0.1 host.docker.internal

Bonus tip 1
If somehow your network settings, or your company VPN network, etc conflicts with OrbStack’s Container IP ranges, update your OrbStack with a different range.

Bonus tip 2
If you omit the step 1, OrbStack will create a randomly named container, but you will still be able use HTTPS without appending any port number. Downside is the container name, thus the domain name will be refreshed every time you rebuild the container.

1개의 좋아요

It seems that Orbstack is to run Docker images. If you’re trying to run production, maybe you’d like to use:

If it’s for development, I think Discourse uses the discourse/discourse_dev - Docker Image image. But you’ll likely have to do your own setup.

FYI, I believe the Docker

command’s code is in discourse/bin/docker/boot_dev at main · discourse/discourse · GitHub.

1개의 좋아요

vscode에 종속되지 않은 분들을 위해, devcontainers CLI만으로 devcontainers를 구성하는 과정은 다음과 같습니다.
devcontainers가 이미 설치되어 있다고 가정합니다:

컨테이너 빌드

git clone https://github.com/discourse/discourse && cd discourse
devcontainer build
devcontainer up --workspace-folder .
devcontainer exec bash

컨테이너 내부로 진입한 후에는 의존성을 빌드해야 합니다.

pnpm install
bundle install
SKIP_MULTISITE=1 SKIP_TEST_DATABASE=1 bin/rake db:create db:migrate
DISCOURSE_DEV_ALLOW_ANON_TO_IMPERSONATE=1 bin/ember-cli -u > /dev/null 2>&1 &
  • 로그를 확인하려면 /dev/null을 다른 파일로 변경하세요.
  • 셸에서 분리된 상태로 실행을 계속 유지하려면 disown을 실행하세요.

discourse 접근

docker inspect <name> | jq '.[0].NetworkSettings.Networks.bridge.IPAddress'

이 명령을 통해 컨테이너에 할당된 IP 주소를 확인할 수 있습니다.
브라우저에서 http://<ipaddress>:4200을 열으세요.

정리

devcontainer를 삭제하려면 (down/delete 옵션은 아직 개발되지 않았습니다)
컨테이너 이름을 가져옵니다.
docker ps
컨테이너를 중지하고 삭제합니다:
docker stop <name> && docker rm <name>
볼륨을 삭제합니다:
docker volume rm discourse-node_modules discourse-pg discourse-redis

4개의 좋아요

VS Code가 아닌 경우의 설명서가 방금 macOS에서 나에게 작동하지 않았습니다. VS Code 외부에서 Discourse Docker 이미지와 상호작용하려는 macOS 사용자는 대신 기존 boot_dev Docker 스크립트를 사용하는 것을 권장합니다.

docker ps를 실행하여 컨테이너 이름(예: peaceful_lumiere와 같은 무작위하고 우스운 이름)을 찾았습니다. docker inspect peaceful_lumiere | jq '.[0].NetworkSettings.Networks.bridge.IPAddress'를 실행했고, IP 주소가 출력되었습니다. 브라우저에서 http://<ip>:4200으로 이동했지만, 무한히 로딩만 되었습니다.

이것은 ember-cli 개발 서버가 모든 인터페이스에서 리스닝하지 않기 때문이라고 생각합니다. 컨테이너 내부에서는 http://127.0.0.1:4200에서만 리스닝하고 있습니다.

결국 .devcontainer/devcontainer.json에 다음과 같은 runArgs 섹션을 추가하여 작동하게 만들었습니다.

     8025, // mailhog
     9229  // chrome remote debug
   ],
+  "runArgs": [
+    "-p",
+    "127.0.0.1:4200:4200",
+    "-p",
+    "127.0.0.1:3000:3000",
+    "-p",
+    "127.0.0.1:9292:9292",
+    "-p",
+    "127.0.0.1:8025:8025",
+    "-p",
+    "127.0.0.1:9229:9229"
+  ],
   "remoteUser": "discourse",
   "remoteEnv": {
     "RAILS_DEVELOPMENT_HOSTS": ".app.github.dev",

… 하지만 이렇게 하면 VS Code에서는 작동하지 않습니다(VS Code 그리고 devcontainer가 모두 포트 포워딩을 시도하기 때문입니다). 별도의 devcontainer-cli.json을 만들고 devcontainer --override-config .devcontainer/devcontainer-cli.json을 사용했는데, 그렇게 하니까 작동했습니다.

하지만 그제서야 깨달았습니다: 이렇게 많은 노력을 기울였지만, 기존 boot_dev 스크립트를 사용하는 것과 비교해 더 나아진 것이 없습니다. 문서화된 단계를 따르는 것이 CLI에서 devcontainer를 올바르게 작동시키려고 애쓰는 것보다 빠르고 쉽습니다.

Dev Containers는 주로 VS Code, 또는 포트 포워딩을 자동으로 관리해 주는 _무언가_와 함께 사용할 때 의도된 것입니다. devcontainer CLI는 그렇게 하지 않습니다. 따라서 VS Code를 원하지 않는다면, Dev Containers를 사용하는 것도 고려해 볼 가치가 없을 수 있습니다.

내 지시사항은 Linux용이었습니다. (제 경우에는 구체적으로 NixOS를 사용했지만) 다른 Linux 기반 시스템에서도 작동하지 않을 이유는 없습니다.

@dfabulich 님의 게시글을 읽었고, 문제를 이해한 것 같습니다. 포트 포워딩은 필요하지 않습니다. 컨테이너의 IP 주소를 사용해야 합니다. 127.0.0.1은 로컬호스트(컨테이너가 아닌 로컬 시스템)를 가리킵니다.

jq 명령어는 포트 포워딩 없이도 접근할 수 있는 로컬 LAN 서브넷 IP를 출력해야 합니다.

아니요, 그걸 제가 했어요. jq"172.17.0.2"를 출력했고, http://172.17.0.2:4200은 영원히 로딩 상태로 멈춰 있었죠.

컨테이너 내부에서 ember-cli는 0.0.0.0:4200이 아니라 127.0.0.1:4200에서 리스닝하고 있습니다. 따라서 172.17.0.2:4200(또는 실제 IP 주소)으로 접근하면 macOS에서는 적어도 에임버(ember)까지 연결이 되지 않습니다.

macOS에서 Docker Desktop은 단순히 가상 머신을 실행할 뿐이라는 점을 유의하세요. macOS에는 "가벼운 프로세스 수준의 Docker 컨테이너"라는 개념이 없습니다.

macOS에 대해 충분히 알지 못해서 Docker가 Linux에서처럼 커널 네임스페이스를 사용하는지 모르겠습니다. 다시 테스트를 해 보았습니다(참고: 서비스가 시작되는 데 시간이 조금 걸립니다):


그렇지 않습니다. macOS용 Docker Desktop은 문자 그대로 QEMU를 실행하고 있습니다. (또는 최근까지 그랬습니다. 지금은 QEMU에 웃긴 모자와 수염을 붙인 것과 같은 새로운 것을 사용하고 있지만, 어쨌든 구현 방식은 여전히 완전한 가상 머신입니다.)

따라서 사용자의 컴퓨터에서는 작동할 것이라고 확신하지만, 제 macOS 컴퓨터에서는 작동하지 않으며, 이것이 가장 그럴듯한 이유라고 생각합니다.

1개의 좋아요