Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docker Image Refresh #2270

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
e0d79a2
feat: create docker dev environment
ojeytonwilliams Nov 16, 2020
a8fd9e1
feat: add devuser to sudoers
ojeytonwilliams Nov 18, 2020
5c7a9fe
docs: add Docker guide to CONTRIBUTING.md
ojeytonwilliams Nov 18, 2020
8f1d402
fix: clarify which code is dev only
ojeytonwilliams Nov 19, 2020
f1018d7
fix(docs): add missing Docker guide
ojeytonwilliams Nov 19, 2020
c1af9ce
fix: include attribution
ojeytonwilliams Nov 19, 2020
3ea09ac
Merge branch 'main' of https://github.com/freeCodeCamp/devdocs into f…
tsengia Jun 22, 2024
8a035d9
use multi-stage Dockerfile to reduce code
tsengia Jun 22, 2024
4309b44
remove .env file
tsengia Jun 22, 2024
f3e1f38
create vscode devcontainer.json file
tsengia Jun 22, 2024
aec83bb
Add .gitattributes to work with Windows better
tsengia Jun 22, 2024
f59abb9
get devcontainer to work with VS Code
tsengia Jun 22, 2024
1220943
Remove compose file
tsengia Jun 22, 2024
2fb2b27
Get docker-from-docker working with VS Code
tsengia Jun 22, 2024
69c8f1f
ignore already downloaded docs when building docker image
tsengia Jun 22, 2024
7f8aa22
make downloaded docs a docker volume
tsengia Jun 22, 2024
da5a924
dynamically get docs origin and production host instead of hard coding
tsengia Jun 22, 2024
9526ddf
changes to get local deployment working
tsengia Jun 22, 2024
45f80ae
fixed referencing wrong variable name
tsengia Jun 22, 2024
a1936a2
Set production docker container CMD
tsengia Jun 22, 2024
dfadd78
switch to building docker image with all docs downloaded
tsengia Jun 23, 2024
d83e30b
Get offline runtime docker image to work
tsengia Jun 23, 2024
3dfd66e
switch to build based devcontainer
tsengia Jun 24, 2024
cf708b2
Add oxipng
tsengia Jun 24, 2024
153d4e6
Add steps to build the runtime docker image
tsengia Jun 24, 2024
d345794
Update docker commands with more examples
tsengia Jun 24, 2024
3c19102
add EditorConfig extension, add code spell words
tsengia Jun 24, 2024
769e9d2
clean up before PR
tsengia Jun 24, 2024
3b25a10
Remove // from docs origin settings and only serve docs pages from ap…
tsengia Jun 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "DevDocs Dev Container",
"build": {
"context": "../",
"dockerfile": "../Dockerfile",
"target": "devdocs-dev"
},
"customizations": {
"vscode": {
"extensions": [
"streetsidesoftware.code-spell-checker",
"mhutchie.git-graph",
"github.vscode-github-actions",
"ms-azuretools.vscode-docker",
"EditorConfig.EditorConfig"
]
}
},
"mounts": [
{"source":"/var/run/docker.sock","target":"/var/run/docker.sock","type": "bind"},
{"source": "devdocs-downloaded","target": "/devdocs/public/docs","type": "volume"}
],
"appPort": 9292
}
6 changes: 6 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,9 @@ Dockerfile*
.dockerignore
.travis.yml
*.md
public/docs/*
public/assets/*
log/*
tmp/*
test/*
.bash_history
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
.DS_Store
.bundle
.bash_history
.env
log
tmp
public/assets
Expand Down
6 changes: 6 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"cSpell.words": [
"devdocs",
"rackup"
]
}
62 changes: 47 additions & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,24 +1,56 @@
FROM ruby:3.3.2
#
# Base layer that both dev and runtime inherit from.
#
FROM ruby:3.3.2-alpine as devdocs-base

ENV LANG=C.UTF-8
ENV ENABLE_SERVICE_WORKER=true

ARG USERNAME=devdocs
ARG USER_ID=1000
ARG GROUP_ID=1000
WORKDIR /devdocs
EXPOSE 9292

RUN apt-get update && \
apt-get -y install git nodejs libcurl4 && \
gem install bundler && \
rm -rf /var/lib/apt/lists/*
COPY Gemfile Gemfile.lock Rakefile Thorfile /devdocs/

COPY Gemfile Gemfile.lock Rakefile /devdocs/
RUN apk --update add nodejs build-base libstdc++ gzip git zlib-dev libcurl oxipng && \
rm -rf /var/cache/apk/* /usr/lib/node_modules

RUN bundle install --system && \
rm -rf ~/.gem /root/.bundle/cache /usr/local/bundle/cache
RUN gem install bundler && \
bundle config set path.system true && \
bundle config set without test && \
bundle install && \
rm -rf ~/.gem /root/.bundle/cache /usr/local/bundle/cache

COPY . /devdocs
RUN addgroup -g $GROUP_ID $USERNAME && \
adduser -u $USER_ID -G $USERNAME -D -h /devdocs $USERNAME && \
chown -R $USERNAME:$USERNAME /devdocs

RUN thor docs:download --all && \
thor assets:compile && \
rm -rf /tmp
#
# Development Image
#
FROM devdocs-base as devdocs-dev
RUN bundle config unset without && \
bundle install && \
apk add --update bash curl && \
curl -LO https://download.docker.com/linux/static/stable/x86_64/docker-26.1.4.tgz && \
tar -xzf docker-26.1.4.tgz && \
mv docker/docker /usr/bin && \
rm -rf docker docker-26.1.4.tgz && \
rm -rf ~/.gem /root/.bundle/cache /usr/local/bundle/cache

EXPOSE 9292
CMD rackup -o 0.0.0.0
VOLUME [ "/devdocs", "/devdocs/public/docs", "/devdocs/public/assets" ]
CMD bash

#
# Runtime Image
#
FROM devdocs-base as devdocs
ENV ENABLE_SERVICE_WORKER=true
COPY . /devdocs/
RUN apk del gzip build-base git zlib-dev && \
chown -R $USERNAME:$USERNAME /devdocs && \
rm -rf /tmp
VOLUME [ "/devdocs/public/docs", "/devdocs/public/assets" ]
USER $USERNAME
CMD rackup --host 0.0.0.0 -E production
20 changes: 0 additions & 20 deletions Dockerfile-alpine

This file was deleted.

51 changes: 45 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,54 @@ The `thor docs:download` command is used to download pre-generated documentation

**Note:** there is currently no update mechanism other than `git pull origin main` to update the code and `thor docs:download --installed` to download the latest version of the docs. To stay informed about new releases, be sure to [watch](https://github.com/freeCodeCamp/devdocs/subscription) this repository.

Alternatively, DevDocs may be started as a Docker container:
## Deploying via Docker
The DevDocs server may also be deployed as a Docker container:

```sh
# First, build the image
git clone https://github.com/freeCodeCamp/devdocs.git && cd devdocs
docker build -t thibaut/devdocs .
# First, pull the image
docker pull devdocs/devdocs

# Next, download documentation that you want, this example downloads the default set of docs, and the ruby docs.
# Use: --default to download the default set of docs
# Use: --all to download ALL available docs (WARNING: Will take a long time!)
docker run --rm \
-v devdocs-docs:/devdocs/public/docs \
-v devdocs-assets:/devdocs/public/assets \
devdocs/devdocs thor docs:download --default ruby

# Now compile the assets. This must be done after you download all the documentation you want.
docker run --rm \
-v devdocs-docs:/devdocs/public/docs \
-v devdocs-assets:/devdocs/public/assets \
devdocs/devdocs thor assets:compile

# Start the DevDocs container (accessible at http://localhost:9292)
docker run \
-v devdocs-docs:/devdocs/public/docs \
-v devdocs-assets:/devdocs/public/assets \
-e DEVDOCS_DISABLE_SSL \
-e DEVDOCS_DOCS_ORIGIN=localhost:9292 \
-e DEVDOCS_HOST=localhost:9292 \
-p 9292:9292 \
devdocs/devdocs
```

The `devdocs-docs` and `devdocs-assets` volumes contain the downloaded documentation and static site data used by the server.

There are multiple environment variables that you can set to configure the DevDocs server.

These can be useful when deploying DevDocs behind a reverse proxy or on your own offline network.

| Environment Variable | Default Value | Description |
|---------------------:|:---------------------|:------------------------------------------------------------------------------------------------|
|`DEVDOCS_DISABLE_SSL` |Not defined | Define this variable to disable HTTPS redirect. |
|`DEVDOCS_HOST` |`devdocs.io` | Hostname that is serving the DevDocs application. |
|`DEVDOCS_DOCS_ORIGIN` |`documents.devdocs.io`| Hostname that is serving the DevDocs documentation pages. |
|`DEVDOCS_DISABLE_HSTS`|Not defined | Define this variable to disable HSTS. If `DEVDOCS_DISABLE_SSL` is defined then this is implied. |

# Finally, start a DevDocs container (access http://localhost:9292)
docker run --name devdocs -d -p 9292:9292 thibaut/devdocs
To build the image fresh, use the below command:
```bash
docker build . -t devdocs/devdocs --target devdocs
```

## Vision
Expand Down
4 changes: 2 additions & 2 deletions assets/javascripts/app/config.js.erb
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
app.config = {
db_filename: 'db.json',
default_docs: <%= App.default_docs.to_json %>,
docs_origin: '<%= App.docs_origin %>',
docs_origin: document.getElementById("docs-origin-meta").content,
env: '<%= App.environment %>',
history_cache_size: 10,
index_filename: 'index.json',
index_path: '/<%= App.docs_prefix %>',
max_results: 50,
production_host: 'devdocs.io',
production_host: document.getElementById("production-host-meta").content,
search_param: 'q',
sentry_dsn: '<%= App.sentry_dsn %>',
version: <%= Time.now.to_i %>,
Expand Down
4 changes: 2 additions & 2 deletions assets/javascripts/models/doc.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ app.models.Doc = class Doc extends app.Model {
}

fileUrl(path) {
return `${app.config.docs_origin}${this.fullPath(path)}?${this.mtime}`;
return `//${app.config.docs_origin}${this.fullPath(path)}?${this.mtime}`;
}

dbUrl() {
return `${app.config.docs_origin}/${this.slug}/${app.config.db_filename}?${this.mtime}`;
return `//${app.config.docs_origin}/${this.slug}/${app.config.db_filename}?${this.mtime}`;
}

indexUrl() {
Expand Down
16 changes: 11 additions & 5 deletions lib/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ class App < Sinatra::Application
Rack::Mime::MIME_TYPES['.webapp'] = 'application/x-web-app-manifest+json'

configure do
use Rack::SslEnforcer, only_environments: ['production', 'test'], hsts: true, force_secure_cookies: false

unless ENV.has_key?('DEVDOCS_DISABLE_SSL')
use Rack::SslEnforcer, only_environments: ['production', 'test'], hsts: !ENV.has_key?('DEVDOCS_DISABLE_HSTS'), force_secure_cookies: false
end

set :sentry_dsn, ENV['SENTRY_DSN']
set :protection, except: [:frame_options, :xss_header]
Expand All @@ -26,6 +29,7 @@ class App < Sinatra::Application
set :assets_compile, %w(*.png docs.js docs.json application.js application.css application-dark.css)

require 'yajl/json_gem'
set :docs_host, ENV.fetch("DEVDOCS_HOST", "devdocs.io")
set :docs_prefix, 'docs'
set :docs_origin, File.join('', docs_prefix)
set :docs_path, File.join(public_folder, docs_prefix)
Expand Down Expand Up @@ -72,7 +76,7 @@ class App < Sinatra::Application

configure :production do
set :static, false
set :docs_origin, '//documents.devdocs.io'
set :docs_origin, ENV.fetch("DEVDOCS_DOCS_ORIGIN", "documents.devdocs.io")
set :csp, "default-src 'self' *; script-src 'self' 'nonce-devdocs' https://www.google-analytics.com https://secure.gaug.es https://*.jquery.com; font-src 'none'; style-src 'self' 'unsafe-inline' *; img-src 'self' * data:;"

use Rack::ConditionalGet
Expand Down Expand Up @@ -125,8 +129,8 @@ def self.parse_news
end

configure :production do
set :docs, parse_docs
set :news, parse_news
set :docs, -> { parse_docs }
set :news, -> { parse_news }
end

helpers do
Expand Down Expand Up @@ -421,8 +425,10 @@ def modern_browser?(browser)
redirect "/#{doc}#{type}/#{query_string_for_redirection}"
elsif rest.length > 1 && rest.end_with?('/')
redirect "/#{doc}#{type}#{rest[0...-1]}#{query_string_for_redirection}"
elsif user_has_docs?(doc) && supports_js_redirection?
elsif !request.path.end_with?(".html") && user_has_docs?(doc) && supports_js_redirection?
redirect_via_js(request.path)
elsif settings.docs_host == settings.docs_origin && File.exist?(File.join(settings.public_folder, "docs", request.path.gsub("..","")))
send_file File.join(settings.public_folder, "docs", request.path.gsub("..","")), status: status
else
response.headers['Content-Security-Policy'] = settings.csp if settings.csp
erb :other
Expand Down
2 changes: 2 additions & 0 deletions views/index.erb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
<meta name="format-detection" content="telephone=no">
<meta name="theme-color" content="#eee">
<meta name="robots" content="noodp">
<meta id="production-host-meta" content="<%= App.docs_host %>" >
<meta id="docs-origin-meta" content="//<%= App.docs_origin %>" >
<title>DevDocs API Documentation</title>
<link rel="canonical" href="<%= canonical_origin %>">
<link rel="manifest" href="/manifest.json">
Expand Down