├── .dockerignore ├── .github ├── FUNDING.yml ├── config.yml ├── dependabot.yml ├── workflows │ ├── main.yml │ └── manual.yml └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── install ├── etc │ ├── services.available │ │ ├── 30-sidekiq │ │ │ └── run │ │ └── 20-discourse │ │ │ └── run │ └── cont-init.d │ │ └── 20-discourse └── assets │ ├── defaults │ └── 20-discourse │ └── functions │ └── 20-discourse ├── LICENSE ├── examples └── compose.yml ├── CHANGELOG.md ├── Dockerfile └── README.md /.dockerignore: -------------------------------------------------------------------------------- 1 | examples/ 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [tiredofit] 2 | -------------------------------------------------------------------------------- /.github/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # Maintain dependencies for GitHub Actions 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" 8 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: "build_image" 2 | 3 | on: 4 | push: 5 | paths: 6 | - "**" 7 | - "!README.md" 8 | 9 | jobs: 10 | build: 11 | uses: tiredofit/github_actions/.github/workflows/default_amd64.yml@main 12 | #uses: tiredofit/github_actions/.github/workflows/default_amd64.yml@main 13 | #uses: tiredofit/github_actions/.github/workflows/default_amd64_armv7_arm64.yml@main 14 | #uses: tiredofit/github_actions/.github/workflows/default_amd64_arm64.yml@main 15 | secrets: inherit 16 | -------------------------------------------------------------------------------- /.github/workflows/manual.yml: -------------------------------------------------------------------------------- 1 | name: "manual_build_image" 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | Manual Build: 7 | description: 'Manual Build' 8 | required: false 9 | 10 | jobs: 11 | build: 12 | uses: tiredofit/github_actions/.github/workflows/default_amd64.yml@main 13 | #uses: tiredofit/github_actions/.github/workflows/default_amd64.yml@main 14 | #uses: tiredofit/github_actions/.github/workflows/default_amd64_armv7_arm64.yml@main 15 | #uses: tiredofit/github_actions/.github/workflows/default_amd64_arm64.yml@main 16 | secrets: inherit 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea or feature 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | --- 11 | name: Feature Request 12 | about: Suggest an idea for this project 13 | 14 | --- 15 | 16 | **Description of the feature** 17 | 18 | 19 | **Benftits of feature** 20 | 21 | 22 | **Additional context** 23 | 24 | -------------------------------------------------------------------------------- /install/etc/services.available/30-sidekiq/run: -------------------------------------------------------------------------------- 1 | #!/command/with-contenv bash 2 | 3 | source /assets/functions/00-container 4 | source /assets/defaults/20-discourse 5 | prepare_service 6 | PROCESS_NAME="sidekiq" 7 | 8 | check_container_initialized 9 | check_service_initialized 20-discourse 10 | liftoff 11 | 12 | print_start "Starting Sidekiq" 13 | cd /app/ 14 | silent sudo -Eu discourse \ 15 | exec bundle exec sidekiq \ 16 | --concurrency ${SIDEKIQ_THREADS} \ 17 | --environment production \ 18 | --logfile "${LOG_PATH}"/"${SIDEKIQ_LOG_FILE}" \ 19 | ${SIDEKIQ_ADDITIONAL_ARGS} >> "${LOG_PATH}"/"${SIDEKIQ_LOG_FILE}" 20 | -------------------------------------------------------------------------------- /install/etc/services.available/20-discourse/run: -------------------------------------------------------------------------------- 1 | #!/command/with-contenv bash 2 | 3 | source /assets/functions/00-container 4 | prepare_service 5 | PROCESS_NAME="rails" 6 | 7 | check_container_initialized 8 | liftoff 9 | 10 | if var_true "${DELIVER_SECURE_ASSETS}" ; then export DISCOURSE_FORCE_HTTPS=true ; fi 11 | export DISCOURSE_SITE_TITLE=${SITE_TITLE} 12 | export UNICORN_WORKERS=${UNICORN_WORKERS} 13 | 14 | cd /app/ 15 | print_start "Starting Unicorn - Discourse version ${DISCOURSE_VERSION}" 16 | s6-setuidgid discourse \ 17 | exec bin/unicorn \ 18 | -E production \ 19 | -o 0.0.0.0 \ 20 | -p "${LISTEN_PORT}" \ 21 | -c "config/unicorn.conf.rb" ${UNICORN_ADDITIONAL_ARGS} 22 | 23 | 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: If something isn't working right.. 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Summary 11 | 12 | 13 | 14 | 15 | ### Steps to reproduce 16 | 17 | 18 | 19 | 20 | ### What is the expected *correct* behavior? 21 | 22 | 23 | 24 | 25 | ### Relevant logs and/or screenshots 26 | 27 | 28 | 29 | ### Environment 30 | 31 | 32 | - Image version / tag: 33 | - Host OS: 34 | 35 |
36 | Any logs | docker-compose.yml 37 |
38 | 39 | 40 | 41 | ### Possible fixes 42 | 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2024 Dave Conroy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /install/etc/cont-init.d/20-discourse: -------------------------------------------------------------------------------- 1 | #!/command/with-contenv bash 2 | 3 | source /assets/functions/00-container 4 | prepare_service 5 | PROCESS_NAME="discourse" 6 | 7 | cat < 2 | 3 | Add EOL notice and deprecate image 4 | 5 | 6 | ## 3.2.17 2025-08-31 7 | 8 | ### Added 9 | - Discourse 3.5.0 10 | 11 | 12 | ## 3.2.16 2025-07-29 13 | 14 | ### Added 15 | - RubyLang 3.3.9 16 | - Discourse 3.4.7 17 | 18 | 19 | ## 3.2.15 2025-06-25 20 | 21 | ### Added 22 | - Discourse 3.4.6 23 | 24 | 25 | ## 3.2.14 2025-06-13 26 | 27 | ### Changed 28 | - Fix issue with Plugins path not linking properly 29 | - Fix issue with Uploads path not being created properly with correct permissions 30 | 31 | 32 | ## 3.2.13 2025-06-09 33 | 34 | ### Added 35 | - Discourse 3.4.5 36 | 37 | ### Changed 38 | - Fix permissions when compiling_assets (credit: DrChat@github) 39 | 40 | 41 | ## 3.2.12 2025-05-28 42 | 43 | ### Added 44 | - Force change ownership of log directory post compilation of assets 45 | 46 | 47 | ## 3.2.11 2025-05-28 48 | 49 | ### Added 50 | - Discourse 3.4.4 51 | 52 | 53 | ## 3.2.10 2025-04-29 54 | 55 | ### Added 56 | - RubyLang 3.3.8 57 | - Discourse 3.4.3 58 | 59 | 60 | ## 3.2.9 2025-03-26 61 | 62 | ### Changed 63 | - Downgrade Ruby 3.3.7 64 | 65 | 66 | ## 3.2.8 2025-03-26 67 | 68 | ### Added 69 | - Discourse 3.4.2 70 | - Ruby 3.3.8 71 | 72 | 73 | ## 3.2.7 2025-02-24 74 | 75 | ### Added 76 | - Ruby Lang 3.3.7 77 | - Discourse 3.4.1 78 | 79 | 80 | ## 3.2.6 2025-02-04 81 | 82 | ### Added 83 | - Discourse 3.4.0 84 | 85 | 86 | ## 3.2.5 2025-02-01 87 | 88 | ### Changed 89 | - Rename mermaid plugin to discourse-mermaid 90 | 91 | 92 | ## 3.2.4 2025-02-01 93 | 94 | ### Changed 95 | - Fix to sidekiq not starting trying to reference old named init script 96 | 97 | 98 | ## 3.2.3 2025-02-01 99 | 100 | ### Changed 101 | - Create /app/tmp ahead of time and set proper permissions 102 | - Set permissions on introducing app plugins 103 | - Fix an issue with a shell alias 104 | 105 | 106 | ## 3.2.2 2024-12-20 107 | 108 | ### Added 109 | - 3.2.1 Patch 110 | 111 | 112 | ## 3.2.1 2024-12-20 113 | 114 | ### Added 115 | - Image cleanup 116 | - Refine Options 117 | - Add rake alias 118 | - Set Mermaid plugin to true 119 | - Change defaults 120 | 121 | 122 | ## 3.2.0 2024-12-19 123 | 124 | ### Added 125 | - Discourse 3.3.3 126 | - Debian Bookworm 127 | - Ruby 3.3.6 128 | - Ability to create admin user and admin pass on first install 129 | - Switch to Unicorn from Puma 130 | - Added more plugin support 131 | 132 | 133 | ## 3.1.4 2023-03-17 134 | 135 | ### Added 136 | - Discourse 3.0.2 137 | 138 | 139 | ## 3.1.3 2023-02-26 140 | 141 | ### Changed 142 | - Fix for building chat plugin 143 | 144 | 145 | ## 3.1.2 2023-02-26 146 | 147 | ### Added 148 | - Discourse 3.0.1 149 | 150 | 151 | ## 3.1.1 2023-02-26 152 | 153 | ### Added 154 | - Discourse 2.8.14 155 | 156 | 157 | ## 3.1.0 2022-12-19 158 | 159 | ### Added 160 | - Change base image to use `tiredofit/nginx` 161 | - Set Nginx to be disabled 162 | - Set Nginx to automatically proxy all requests in to 127.0.0.1:3000 163 | 164 | 165 | ## 3.0.1 2022-12-16 166 | 167 | ### Changed 168 | - Remove directories that are not necessary to reduce image size 169 | 170 | 171 | ## 3.0.0 2022-12-15 172 | 173 | This has breaking changes all over the image, specifically related to paths and environment variables. Please read the README.md carefully and view examples and port over accordingly. 174 | 175 | ### Added 176 | - Discourse 2.8.13 177 | - Debian Bullseye 178 | - Ruby 3.0.5 compiled w/ JemAlloc 179 | - Node 16 180 | - Added new image optimization packages 181 | - Postgresql 15 Support 182 | - Rewrote initialization routines and configured configurable paths for uploads, backups, plugins, logs 183 | - Logrotate routines for all logs 184 | - Switchable environment variables for plugins 185 | - New plugins added: Footnote, Formatting Toolbar, Mermaid, Post Voting, Spoiler Alert 186 | 187 | ### Changed 188 | - Reworked all environment variables, now use standard variables for those used to other tiredofit images 189 | 190 | 191 | ## 2.5.1 2021-12-15 192 | 193 | ### Added 194 | - Discourse 2.7.9 195 | 196 | 197 | ## 2.5.0 2020-07-17 198 | 199 | ### Added 200 | - Update to Discourse 2.6.0-beta1 201 | - Remove some plugins 202 | 203 | 204 | ## 2.4.1 2019-11-29 205 | 206 | ### Added 207 | - Discourse 2.3.6 208 | 209 | ### Changed 210 | - Ruby 2.6 211 | 212 | ## 2.4 2019-09-01 213 | 214 | * Update Discourse version to 2.3.2 215 | 216 | ## 2.3 2019-07-02 217 | 218 | * Discourse 2.3.1 219 | 220 | ## 2.2.1 2019-03-26 221 | 222 | * Discourse 2.2.3 223 | 224 | ## 2.2 2019-02-28 225 | 226 | * Discourse 2.2.0 227 | * Ruby 2.5 228 | * NodeJS 11 229 | 230 | ## 2.1-dev 2018-08-26 231 | 232 | * Putting Nginx in front of 3000 for CORS 233 | 234 | ## 2.0.2 2018-08-26 235 | 236 | * Bump to 2.0.4 237 | 238 | ## 2.01 2018-07-10 239 | 240 | * Bump to 2.02 241 | 242 | ## 2.0 2018-06-04 243 | 244 | * Migrate to Debian Stretch 245 | * Ruby 2.4 246 | * Discourse 2.0 247 | 248 | ## 1.4 2018-02-01 249 | 250 | * Rebase 251 | 252 | ## 1.3 2017-10-19 253 | 254 | * Version Bump and Cleanup 255 | 256 | 257 | ## 1.2 2017-08-25 258 | 259 | * A few more plugins added 260 | 261 | ## 1.1 2017-08-25 262 | 263 | * Major Cleanup 264 | * Added a few plugins specific to SelfDesign and BB-Code Colour 265 | 266 | ## 1.0 2017-08-06 267 | 268 | * Initial Release 269 | * Debian Base 270 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | 2 | 3 | ARG DISTRO="debian" 4 | ARG DISTRO_VARIANT="bookworm" 5 | 6 | FROM docker.io/tiredofit/nginx:${DISTRO}-${DISTRO_VARIANT} 7 | LABEL maintainer="Dave Conroy (github.com/tiredofit)" 8 | 9 | ARG DISCOURSE_VERSION 10 | ARG RUBY_VERSION 11 | 12 | ### Environment Variables 13 | ENV DISCOURSE_VERSION=${DISCOURSE_VERSION:-"v3.5.0"} \ 14 | RUBY_VERSION=${RUBY_VERSION:-"3.3.9"} \ 15 | RUBY_ALLOCATOR=/usr/lib/libjemalloc.so.2 \ 16 | RAILS_ENV=production \ 17 | RUBY_GC_MALLOC_LIMIT=90000000 \ 18 | RUBY_GLOBAL_METHOD_CACHE_SIZE=131072 \ 19 | PATH=/usr/local/share/pnpm:$PATH \ 20 | ENABLE_NGINX=FALSE \ 21 | NGINX_MODE=PROXY \ 22 | NGINX_PROXY_URL=http://127.0.0.1:3000 \ 23 | NGINX_ENABLE_CREATE_SAMPLE_HTML=FALSE \ 24 | IMAGE_NAME="tiredofit/discourse" \ 25 | IMAGE_REPO_URL="https://github.com/tiredofit/docker-discourse/" 26 | 27 | ### Install Dependencies 28 | RUN source /assets/functions/00-container && \ 29 | BUILD_DEPS=" \ 30 | build-essential \ 31 | g++ \ 32 | gcc \ 33 | gettext \ 34 | libbz2-dev \ 35 | libfreetype6-dev \ 36 | libicu-dev \ 37 | libjemalloc-dev \ 38 | libjpeg-dev \ 39 | libssl-dev \ 40 | libpq-dev \ 41 | libtiff-dev \ 42 | libxslt-dev \ 43 | libxml2-dev \ 44 | libyaml-dev \ 45 | make \ 46 | patch \ 47 | pkg-config \ 48 | zlib1g-dev \ 49 | " && \ 50 | set -x && \ 51 | addgroup --gid 9009 --system discourse && \ 52 | adduser --uid 9009 --gid 9009 --home /dev/null --gecos "Discourse" --shell /sbin/nologin --disabled-password discourse && \ 53 | curl -sSL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ 54 | echo "deb https://deb.nodesource.com/node_22.x nodistro main" > /etc/apt/sources.list.d/nodejs.list && \ 55 | curl -ssL https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - && \ 56 | echo "deb http://apt.postgresql.org/pub/repos/apt/ $(cat /etc/os-release |grep "VERSION=" | awk 'NR>1{print $1}' RS='(' FS=')')-pgdg main" > /etc/apt/sources.list.d/postgres.list && \ 57 | package update && \ 58 | package upgrade -y && \ 59 | package install \ 60 | ${BUILD_DEPS} \ 61 | advancecomp \ 62 | brotli \ 63 | ghostscript \ 64 | gifsicle \ 65 | git \ 66 | gsfonts \ 67 | imagemagick \ 68 | jhead \ 69 | jpegoptim \ 70 | libicu72 \ 71 | libjemalloc2 \ 72 | libjpeg-turbo-progs \ 73 | libpq5 \ 74 | libssl3 \ 75 | libxml2 \ 76 | nodejs \ 77 | npm \ 78 | optipng \ 79 | pngquant \ 80 | postgresql-client-17 \ 81 | postgresql-contrib-17 \ 82 | zlib1g \ 83 | && \ 84 | \ 85 | mkdir -p /usr/src/oxipng && \ 86 | curl -sSL https://github.com/shssoichiro/oxipng/releases/download/v7.0.0/oxipng-7.0.0-x86_64-unknown-linux-musl.tar.gz | tar xvfz - --strip 1 -C /usr/src/oxipng && \ 87 | cp -R /usr/src/oxipng/oxipng /usr/bin && \ 88 | \ 89 | ### Setup Ruby 90 | mkdir -p /usr/src/ruby && \ 91 | curl -sSL https://cache.ruby-lang.org/pub/ruby/$(echo ${RUBY_VERSION} | cut -c1-3)/ruby-${RUBY_VERSION}.tar.gz | tar xvfz - --strip 1 -C /usr/src/ruby && \ 92 | cd /usr/src/ruby && \ 93 | ./configure \ 94 | --disable-install-rdoc \ 95 | --enable-shared \ 96 | --with-jemalloc \ 97 | && \ 98 | make -j$(getconf _NPROCESSORS_ONLN) && \ 99 | make install && \ 100 | \ 101 | echo 'gem: --no-document' >> /usr/local/etc/gemrc && \ 102 | gem update --system && \ 103 | \ 104 | npm install --global \ 105 | svgo \ 106 | terser \ 107 | uglify-js \ 108 | pnpm@9 \ 109 | && \ 110 | \ 111 | clone_git_repo "https://github.com/discourse/discourse" "${DISCOURSE_VERSION}" /app && \ 112 | BUNDLER_VERSION="$(grep "BUNDLED WITH" Gemfile.lock -A 1 | grep -v "BUNDLED WITH" | tr -d "[:space:]")" && \ 113 | gem install bundler:"${BUNDLER_VERSION}" && \ 114 | chown -R discourse:discourse /app && \ 115 | bundle config build.nokogiri --use-system-libraries && \ 116 | bundle config --local path ./vendor/bundle && \ 117 | bundle config set --local deployment true && \ 118 | bundle config set --local without development test && \ 119 | bundle install --jobs $(nproc) && \ 120 | cd /app && \ 121 | git config --global --add safe.directory /app && \ 122 | mkdir -p /usr/local/share/pnpm && \ 123 | pnpm install --frozen-lockfile && \ 124 | #pnpm run postinstall && \ 125 | #pnpm cache clean && \ 126 | pnpm cache delete && \ 127 | find /app/vendor/bundle -name tmp -type d -exec rm -rf {} + && \ 128 | curl -sSL https://git.io/GeoLite2-ASN.mmdb -o /app/vendor/data/GeoLite2-ASN.mmdb && \ 129 | curl -sSL https://git.io/GeoLite2-City.mmdb -o /app/vendor/data/GeoLite2-City.mmdb && \ 130 | sed -i "5i\ \ require 'uglifier'" /app/config/environments/production.rb && \ 131 | sed -i "s|config.assets.js_compressor = :uglifier|config.assets.js_compressor = Uglifier.new(harmony: true)|g" /app/config/environments/production.rb && \ 132 | ln -sf "$(which convert)" "/usr/bin/magick" && \ 133 | \ 134 | mkdir -p /assets/discourse/plugins && \ 135 | mv /app/plugins/* /assets/discourse/plugins && \ 136 | rm -rf /assets/discourse/plugins/discourse-nginx-performance-report && \ 137 | ### Allow Same Origin 138 | git clone https://github.com/TheBunyip/discourse-allow-same-origin.git /assets/discourse/plugins/allow-same-origin && \ 139 | ### Allow Accepted Answers on Topics 140 | git clone https://github.com/discourse/discourse-solved /assets/discourse/plugins/solved && \ 141 | #### Assign Plugin 142 | git clone https://github.com/discourse/discourse-assign /assets/discourse/plugins/assign && \ 143 | #### Events Plugin 144 | git clone https://github.com/angusmcleod/discourse-events /assets/discourse/plugins/events && \ 145 | #### Formatting Toolbar Plugin 146 | git clone https://github.com/MonDiscourse/discourse-formatting-toolbar /assets/discourse/plugins/formatting-toolbar && \ 147 | #### Mermaid 148 | git clone https://github.com/unfoldingWord/discourse-mermaid /assets/discourse/plugins/discourse-mermaid && \ 149 | #### Post Voting 150 | git clone https://github.com/discourse/discourse-post-voting /assets/discourse/plugins/post-voting && \ 151 | ### Push Notifications 152 | git clone https://github.com/discourse/discourse-push-notifications /assets/discourse/plugins/push && \ 153 | ### Adds the ability for voting on a topic in category 154 | git clone https://github.com/discourse/discourse-voting.git /assets/discourse/plugins/voting && \ 155 | chown -R discourse:discourse \ 156 | /assets/discourse \ 157 | /app \ 158 | && \ 159 | ### Cleanup 160 | package remove ${BUILD_DEPS} && \ 161 | package cleanup && \ 162 | rm -rf \ 163 | /app/.devcontainer \ 164 | /app/.editorconfig \ 165 | /app/.github \ 166 | /app/.*ignore \ 167 | /app/.prettier* \ 168 | /app/.vscode-sample \ 169 | /app/bin/docker \ 170 | /app/Brewfile \ 171 | /app/CODEOWNERS \ 172 | /app/CONTRIBUTING.md \ 173 | /app/config/dev_defaults.yml \ 174 | /app/config/*.sample \ 175 | /app/config/logrotate.conf \ 176 | /app/config/multisite.yml.production-sample \ 177 | /app/config/nginx* \ 178 | /app/config/puma* \ 179 | /app/config/unicorn_upstart.conf \ 180 | /app/deploy.rb.sample \ 181 | /app/d \ 182 | /app/discourse.sublime-project \ 183 | /app/install-imagemagick \ 184 | /app/lefthook.yml \ 185 | /app/test \ 186 | /app/translator.yml \ 187 | /app/vendor/bundle/ruby/${RUBY_VERSION:0:3}/cache/* \ 188 | /root/.bundle \ 189 | /root/.config \ 190 | /root/.local \ 191 | /root/.npm \ 192 | /root/.profile \ 193 | /tmp/* \ 194 | /usr/src/* 195 | 196 | WORKDIR /app 197 | EXPOSE 3000 198 | COPY install/ / 199 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # github.com/tiredofit/docker-discourse 2 | 3 | [![GitHub release](https://img.shields.io/github/v/tag/tiredofit/docker-discourse?style=flat-square)](https://github.com/tiredofit/docker-discourse/releases/latest) 4 | [![Build Status](https://img.shields.io/github/actions/workflow/status/tiredofit/docker-discourse/main.yml?branch=main&style=flat-square)](https://github.com/tiredofit/docker-discourse/actions) 5 | [![Docker Stars](https://img.shields.io/docker/stars/tiredofit/discourse.svg?style=flat-square&logo=docker)](https://hub.docker.com/r/tiredofit/discourse/) 6 | [![Docker Pulls](https://img.shields.io/docker/pulls/tiredofit/discourse.svg?style=flat-square&logo=docker)](https://hub.docker.com/r/tiredofit/discourse/) 7 | [![Become a sponsor](https://img.shields.io/badge/sponsor-tiredofit-181717.svg?logo=github&style=flat-square)](https://github.com/sponsors/tiredofit) 8 | [![Paypal Donate](https://img.shields.io/badge/donate-paypal-00457c.svg?logo=paypal&style=flat-square)](https://www.paypal.me/tiredofit) 9 | 10 | * * * 11 | ## About 12 | 13 | This will build a Docker Image for [Discourse](https://www.discourse.org/) - A web based discussion forum. 14 | 15 | * Unlike the official Discourse image, this is meant to be self contained without requiring a base image or use the `launcher` 16 | * Additional Plugins installed 17 | * Flexible Volatile Storage 18 | 19 | 20 | [Changelog](CHANGELOG.md) 21 | 22 | ## Maintainer 23 | 24 | - [Dave Conroy](http://github/tiredofit/) 25 | 26 | ## Table of Contents 27 | 28 | - [About](#about) 29 | - [Maintainer](#maintainer) 30 | - [Table of Contents](#table-of-contents) 31 | - [Prerequisites and Assumptions](#prerequisites-and-assumptions) 32 | - [Installation](#installation) 33 | - [Build from Source](#build-from-source) 34 | - [Prebuilt Images](#prebuilt-images) 35 | - [Configuration](#configuration) 36 | - [Quick Start](#quick-start) 37 | - [Persistent Storage](#persistent-storage) 38 | - [Base Images used](#base-images-used) 39 | - [Container Options](#container-options) 40 | - [Admin Options](#admin-options) 41 | - [Log Options](#log-options) 42 | - [Performance Options](#performance-options) 43 | - [Database Options](#database-options) 44 | - [Postgresql](#postgresql) 45 | - [Redis](#redis) 46 | - [SMTP Options](#smtp-options) 47 | - [Plugins](#plugins) 48 | - [Networking](#networking) 49 | - [Maintenance](#maintenance) 50 | - [Shell Access](#shell-access) 51 | - [Support](#support) 52 | - [Usage](#usage) 53 | - [Bugfixes](#bugfixes) 54 | - [Feature Requests](#feature-requests) 55 | - [Updates](#updates) 56 | - [License](#license) 57 | 58 | ## Prerequisites and Assumptions 59 | * Assumes you are using some sort of SSL terminating reverse proxy such as: 60 | * [Traefik](https://github.com/tiredofit/docker-traefik) 61 | * [Nginx](https://github.com/jc21/nginx-proxy-manager) 62 | * [Caddy](https://github.com/caddyserver/caddy) 63 | * Requires access to a Postgres Server 64 | * Requires access to a Redis Server 65 | 66 | ## Installation 67 | 68 | ### Build from Source 69 | Clone this repository and build the image with `docker build -t (imagename) .` 70 | 71 | ### Prebuilt Images 72 | Builds of the image are available on [Docker Hub](https://hub.docker.com/r/tiredofit/discourse) 73 | 74 | ```bash 75 | docker pull docker.io/tiredofit/discourse:(imagetag) 76 | ``` 77 | 78 | Builds of the image are also available on the [Github Container Registry](https://github.com/tiredofit/docker-discourse/pkgs/container/docker-discourse) 79 | 80 | ``` 81 | docker pull ghcr.io/tiredofit/docker-discourse:(imagetag) 82 | ``` 83 | 84 | The following image tags are available along with their tagged release based on what's written in the [Changelog](CHANGELOG.md): 85 | 86 | | Container OS | Tag | 87 | | ------------ | --------- | 88 | | Debian | `:latest` | 89 | 90 | ## Configuration 91 | 92 | ### Quick Start 93 | 94 | - The quickest way to get started is using [docker-compose](https://docs.docker.com/compose/). See the examples folder for a working [compose.yml](examples/compose.yml) that can be modified for development or production use. 95 | 96 | - Set various [environment variables](#environment-variables) to understand the capabilities of this image. 97 | - Map [persistent storage](#data-volumes) for access to configuration and data files for backup. 98 | - Make [networking ports](#networking) available for public access if necessary 99 | 100 | **The first boot can take from 2 minutes - 5 minutes depending on your CPU to setup the proper schemas and precompile assets** 101 | 102 | 103 | ### Persistent Storage 104 | 105 | The container operates heavily from the `/app` folder, however there are a few folders that should be persistently mapped to ensure data persistence. The following directories are used for configuration and can be mapped for persistent storage. 106 | 107 | | Directory | Description | 108 | | --------------- | ----------------- | 109 | | `/data/logs` | Logfiles | 110 | | `/data/uploads` | Uploads Directory | 111 | | `/data/backups` | Backups Directory | 112 | | `/data/plugins` | Plugins Driectory | 113 | 114 | #### Base Images used 115 | 116 | This image relies on a [Debian Linux](https://hub.docker.com/r/tiredofit/debian) base image that relies on an [init system](https://github.com/just-containers/s6-overlay) for added capabilities. Outgoing SMTP capabilities are handlded via `msmtp`. Individual container performance monitoring is performed by [zabbix-agent](https://zabbix.org). Additional tools include: `bash`,`curl`,`less`,`logrotate`,`nano`. 117 | 118 | Be sure to view the following repositories to understand all the customizable options: 119 | 120 | | Image | Description | 121 | | ------------------------------------------------------ | -------------------------------------- | 122 | | [OS Base](https://github.com/tiredofit/docker-debian/) | Customized Image based on Debian Linux | 123 | | [Nginx](https://github.com/tiredofit/docker-nginx/) | Nginx webserver | 124 | 125 | 126 | #### Container Options 127 | | Parameter | Description | Default | 128 | | -------------------------- | ------------------------------------------------------------------ | ---------------------- | 129 | | `BACKUP_PATH` | Place to store in app backups | `{DATA_PATH}/backups/` | 130 | | `DELIVER_SECURE_ASSETS` | Enable serving of HTTPS assets | `FALSE` | 131 | | `ENABLE_DB_MIGRATE` | Enable DB Migrations on startup | `TRUE` | 132 | | `ENABLE_MINIPROFILER` | Enable Mini Profiler | `FALSE` | 133 | | `ENABLE_PRECOMPILE_ASSETS` | Enable Precompiling Assets on statup | `TRUE` | 134 | | `SETUP_MODE` | Automatically generate config based on these environment variables | `AUTO` | 135 | | `ENABLE_CORS` | Enable CORS | `FALSE` | 136 | | `CORS_ORIGIN` | CORS Origin | `` | 137 | | `UPLOADS_PATH` | Path to store Uploads | `{DATA_PATH}/uploads/` | 138 | 139 | #### Admin Options 140 | 141 | >> Only used on first boot 142 | 143 | | Parameter | Description | Default | 144 | | ------------- | ------------------------------------------- | --------------------- | 145 | | `ADMIN_USER` | Username for admin | `admin` | 146 | | `ADMIN_EMAIL` | Admin email address | `admin@example.com` | 147 | | `ADMIN_PASS` | Admin password - Must be over 10 characters | `tiredofit-discourse` | 148 | | `ADMIN_NAME` | Admin Name (First and Last) | `Admin User` | 149 | 150 | #### Log Options 151 | | Parameter | Description | Default | 152 | | ------------------------ | ---------------------- | ------------------- | 153 | | `LOG_FILE` | Discourse Log File | `discourse.log` | 154 | | `LOG_LEVEL` | Discourse Log Level | `info` | 155 | | `LOG_PATH` | Path to store logfiles | `{DATA_PATH}/logs/` | 156 | | `UNICORN_LOG_FILE` | Unicorn Log | `unicorn.log` | 157 | | `UNICORN_LOG_ERROR_FILE` | Unicorn Error Log | `unicorn_error.log` | 158 | | `SIDEKIQ_LOG_FILE` | SideKiq Log | `sidekiq.log` | 159 | 160 | #### Performance Options 161 | | Parameter | Description | Default | 162 | | ----------------- | ------------------- | ------- | 163 | | `UNICORN_WORKERS` | How many Workers | `8` | 164 | | `SIDEKIQ_THREADS` | Sidekiq Concurrency | `25` | 165 | 166 | 167 | #### Database Options 168 | 169 | ##### Postgresql 170 | | Parameter | Description | Default | 171 | | -------------------- | --------------------------------------------- | ------- | 172 | | `DB_POOL` | How many Database connections | `8` | 173 | | `DB_PORT` | Database Port | `5432` | 174 | | `DB_TIMEOUT` | Timeout for established connection in seconds | `5000` | 175 | | `DB_TIMEOUT_CONNECT` | Connection Timeout in Seconds | `5` | 176 | | `DB_USER` | Username of Database | | 177 | | `DB_NAME` | Database name | | 178 | | `DB_PASS` | Database Password | | 179 | | `DB_HOST` | Hostname of Database Server | | 180 | 181 | ##### Redis 182 | | Parameter | Description | Default | 183 | | ---------------------------- | ------------------------------------------- | ------- | 184 | | `REDIS_DB` | Redis Database Number | `0` | 185 | | `REDIS_ENABLE_TLS` | Enable TLS when communication to REDIS_HOST | `FALSE` | 186 | | `REDIS_PORT` | Redis Host Listening Port | `6379` | 187 | | `REDIS_SKIP_CLIENT_COMMANDS` | Skip client commands if unsupported | `FALSE` | 188 | 189 | #### SMTP Options 190 | | Parameter | Description | Default | 191 | | --------------------- | ---------------------------------------- | --------------- | 192 | | `SMTP_AUTHENTICATION` | SMTP Authentication type `plain` `login` | `plain` | 193 | | `SMTP_DOMAIN` | HELO Domain for remote SMTP Host | `example.com` | 194 | | `SMTP_HOST` | SMTP Hostname | `postfix-relay` | 195 | | `SMTP_USER` | SMTP Username | | 196 | | `SMTP_PASS` | SMTP Username | | 197 | | `SMTP_PORT` | SMTP Port | `25` | 198 | | `SMTP_START_TLS` | Enable STARTTLS on connection | `TRUE` | 199 | | `SMTP_TLS_FORCE` | Force TLS on connection | `FALSE` | 200 | | `SMTP_TLS_VERIFY` | TLS Certificate verification | `none` | 201 | 202 | #### Plugins 203 | | Parameter | Description | Default | 204 | | ---------------------------------- | ----------------------------- | ---------------------- | 205 | | `PLUGIN_PATH` | Path where plugins are stored | `{DATA_PATH}/plugins/` | 206 | | `PLUGIN_ENABLE_AUTOMATION` | | `FALSE` | 207 | | `PLUGIN_ENABLE_ASSIGN` | | `FALSE` | 208 | | `PLUGIN_ENABLE_CHAT_INTEGRATION` | | `FALSE` | 209 | | `PLUGIN_ENABLE_CHECKLIST` | | `FALSE` | 210 | | `PLUGIN_ENABLE_DETAILS` | | `TRUE` | 211 | | `PLUGIN_ENABLE_EVENTS` | | `FALSE` | 212 | | `PLUGIN_ENABLE_FOOTNOTES` | | `FALSE` | 213 | | `PLUGIN_ENABLE_FORMATTING_TOOLBAR` | | `FALSE` | 214 | | `PLUGIN_ENABLE_LAZY_VIDEOS` | | `TRUE` | 215 | | `PLUGIN_ENABLE_LOCAL_DATES` | | `TRUE` | 216 | | `PLUGIN_ENABLE_MERMAID` | | `TRUE` | 217 | | `PLUGIN_ENABLE_NARRATIVE_BOT` | | `TRUE` | 218 | | `PLUGIN_ENABLE_POLLS` | | `TRUE` | 219 | | `PLUGIN_ENABLE_POST_VOTING` | | `FALSE` | 220 | | `PLUGIN_ENABLE_PRESENCE` | | `TRUE` | 221 | | `PLUGIN_ENABLE_PUSH_NOTIFICATIONS` | | `FALSE` | 222 | | `PLUGIN_ENABLE_SAME_ORIGIN` | | `FALSE` | 223 | | `PLUGIN_ENABLE_SOLVED` | | `FALSE` | 224 | | `PLUGIN_ENABLE_SPOILER_ALERT` | | `FALSE` | 225 | | `PLUGIN_ENABLE_STYLEGUIDE` | | `TRUE` | 226 | | `PLUGIN_ENABLE_VOTING` | | `FALSE` | 227 | 228 | ### Networking 229 | 230 | The following ports are exposed. 231 | 232 | | Port | Description | 233 | | ------ | ----------- | 234 | | `3000` | Unicorn | 235 | 236 | * * * 237 | ## Maintenance 238 | 239 | ### Shell Access 240 | 241 | For debugging and maintenance purposes you may want access the containers shell. 242 | 243 | ``bash 244 | docker exec -it (whatever your container name is) bash 245 | `` 246 | 247 | Try using the command `rake --tasks` 248 | 249 | ## Support 250 | 251 | These images were built to serve a specific need in a production environment and gradually have had more functionality added based on requests from the community. 252 | ### Usage 253 | - The [Discussions board](../../discussions) is a great place for working with the community on tips and tricks of using this image. 254 | - [Sponsor me](https://tiredofit.ca/sponsor) for personalized support 255 | ### Bugfixes 256 | - Please, submit a [Bug Report](issues/new) if something isn't working as expected. I'll do my best to issue a fix in short order. 257 | 258 | ### Feature Requests 259 | - Feel free to submit a feature request, however there is no guarantee that it will be added, or at what timeline. 260 | - [Sponsor me](https://tiredofit.ca/sponsor) regarding development of features. 261 | 262 | ### Updates 263 | - Best effort to track upstream changes, More priority if I am actively using the image in a production environment. 264 | - [Sponsor me](https://tiredofit.ca/sponsor) for up to date releases. 265 | 266 | ## License 267 | MIT. See [LICENSE](LICENSE) for more details. 268 | # References 269 | 270 | * https://www.discourse.org 271 | 272 | 273 | -------------------------------------------------------------------------------- /install/assets/functions/20-discourse: -------------------------------------------------------------------------------- 1 | #!/usr/bin/with-contenv bash 2 | 3 | bootstrap_filesystem() { 4 | if [ ! -d "${DATA_PATH}" ]; then 5 | mkdir -p "${DATA_PATH}" 6 | fi 7 | if [ $(stat -c %U "${DATA_PATH}") != "discourse" ] ; then chown discourse:discourse "${DATA_PATH}" ; fi 8 | 9 | if [ ! -d "${BACKUP_PATH}" ]; then 10 | mkdir -p "${BACKUP_PATH}" 11 | fi 12 | if [ "${BACKUP_PATH}" != "/app/public/backups/" ] ; then 13 | rm -rf /app/public/backups 14 | ln -sf "${BACKUP_PATH}" /app/public/backups 15 | fi 16 | if [ $(stat -c %U "${BACKUP_PATH}") != "discourse" ] ; then chown discourse:discourse "${BACKUP_PATH}" ; fi 17 | 18 | if [ ! -d "${LOG_PATH}" ] ; then 19 | mkdir -p "${LOG_PATH}" 20 | fi 21 | if [ $(stat -c %U "${LOG_PATH}") != "discourse" ] ; then chown -R discourse:discourse "${LOG_PATH}" ; fi 22 | 23 | if [ "${LOG_PATH}" != "/app/log/" ] ; then 24 | rm -rf /app/log 25 | ln -sf "${LOG_PATH}" /app/log 26 | fi 27 | 28 | create_logrotate discourse "${LOG_PATH}"/${LOG_FILE} discourse discourse 29 | create_logrotate discourse_unicorn "${UNICORN_LOG_PATH}"/${UNICORN_LOG_FILE} discourse discourse 30 | create_logrotate discourse_unicorn_error "${UNICORN_LOG_PATH}"/${UNICORN_LOG_ERROR_FILE} discourse discourse 31 | create_logrotate discourse_sidekiq "${LOG_PATH}"/${SIDEKIQ_LOG_FILE} discourse discourse 32 | 33 | #chown -R discourse:discourse /app "${LOG_PATH}" 34 | 35 | if [ ! -d "${PLUGIN_PATH}" ]; then 36 | mkdir -p "${PLUGIN_PATH}" 37 | fi 38 | if [ "${PLUGIN_PATH}" != "/app/plugins/" ] ; then 39 | rm -rf /app/plugins 40 | ln -sf "${PLUGIN_PATH}" /app/plugins 41 | fi 42 | if [ $(stat -c %U "${PLUGIN_PATH}") != "discourse" ] ; then chown discourse:discourse "${PLUGIN_PATH}" ; fi 43 | 44 | if [ ! -d "${UPLOADS_PATH}" ]; then 45 | mkdir -p "${UPLOADS_PATH}" 46 | fi 47 | 48 | if [ "${UPLOADS_PATH}" != "/app/public/uploads/" ] ; then 49 | rm -rf /app/public/uploads 50 | ln -sf "${UPLOADS_PATH}" /app/public/uploads 51 | fi 52 | 53 | if [ $(stat -c %U "${UPLOADS_PATH}") != "discourse" ] ; then chown discourse:discourse "${UPLOADS_PATH}" ; fi 54 | 55 | mkdir -p \ 56 | /app/tmp/cache \ 57 | /app/tmp/pids 58 | 59 | chown -R discourse:discourse /app/tmp 60 | } 61 | 62 | configure_discourse() { 63 | sanity_db postgres 64 | db_ready postgres 65 | sanity_db redis 66 | db_ready redis 67 | 68 | cat <> /root/.bashrc 559 | } 560 | --------------------------------------------------------------------------------