Skip to content

Commit 472207e

Browse files
committedFeb 4, 2022
local development environment using docker
1 parent 489ea97 commit 472207e

11 files changed

+381
-86
lines changed
 

‎.dockerignore

+7-2
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,18 @@
88
public/system
99
public/assets
1010
public/packs
11-
node_modules
1211
neo4j
13-
vendor/bundle
1412
.DS_Store
1513
*.swp
1614
*~
1715
postgres
1816
redis
1917
elasticsearch
2018
chart
19+
.git
20+
.cache
21+
.vagrant
22+
docker/data
23+
docker/cache
24+
vendor
25+
node_modules

‎.env.docker

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
LOCAL_DOMAIN=mastodon.local
2+
WEB_DOMAIN=localhost:3000
3+
4+
DB_HOST=db
5+
DB_USER=mastodon
6+
DB_NAME=mastodon
7+
DB_PASS=mastodon
8+
9+
REDIS_HOST=redis

‎.gitignore

+10-5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77
# Ignore bundler config and downloaded libraries.
88
/.bundle
99
/vendor/bundle
10+
/vendor/cache
11+
12+
# Ignore yarn config and downloaded libraries.
13+
/node_modules/
14+
/.cache/
15+
/.yarn/
1016

1117
# Ignore the default SQLite database.
1218
/db/*.sqlite3
@@ -25,8 +31,8 @@
2531
.env
2632
.env.production
2733
.env.development
28-
/node_modules/
2934
/build/
35+
.docker-db-initialized
3036

3137
# Ignore Vagrant files
3238
.vagrant/
@@ -38,10 +44,9 @@
3844
.vscode/
3945
.idea/
4046

41-
# Ignore postgres + redis + elasticsearch volume optionally created by docker-compose
42-
/postgres
43-
/redis
44-
/elasticsearch
47+
# Ignore volumes optionally created by docker-compose
48+
/docker/data
49+
/docker/cache
4550

4651
# ignore Helm dependency charts
4752
/chart/charts/*.tgz

‎.yarnrc

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Yarn constantly fails on this causing long timeouts after successful installs
2+
disable-self-update-check true

‎Dockerfile

+148-76
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
1+
#syntax=docker/dockerfile:1.2
12
FROM ubuntu:20.04 as build-dep
23

34
# Use bash for the shell
45
SHELL ["/bin/bash", "-c"]
56

7+
# Enable super fast apt caches for use with --mount=type=cache
8+
RUN rm -f /etc/apt/apt.conf.d/docker-clean; \
9+
echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
10+
11+
ENV PATH="/opt/ruby/bin:/opt/node/bin:/opt/mastodon/bin:${PATH}"
12+
613
# Install Node v12 (LTS)
714
ENV NODE_VER="12.21.0"
8-
RUN ARCH= && \
9-
dpkgArch="$(dpkg --print-architecture)" && \
15+
RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \
16+
--mount=type=cache,sharing=locked,target=/var/lib/apt \
17+
ARCH= && \
18+
dpkgArch="$(dpkg --print-architecture)" && \
1019
case "${dpkgArch##*-}" in \
1120
amd64) ARCH='x64';; \
1221
ppc64el) ARCH='ppc64le';; \
@@ -16,102 +25,165 @@ RUN ARCH= && \
1625
i386) ARCH='x86';; \
1726
*) echo "unsupported architecture"; exit 1 ;; \
1827
esac && \
19-
echo "Etc/UTC" > /etc/localtime && \
20-
apt-get update && \
21-
apt-get install -y --no-install-recommends ca-certificates wget python && \
22-
cd ~ && \
23-
wget -q https://nodejs.org/download/release/v$NODE_VER/node-v$NODE_VER-linux-$ARCH.tar.gz && \
24-
tar xf node-v$NODE_VER-linux-$ARCH.tar.gz && \
25-
rm node-v$NODE_VER-linux-$ARCH.tar.gz && \
26-
mv node-v$NODE_VER-linux-$ARCH /opt/node
28+
echo "Etc/UTC" > /etc/localtime && \
29+
apt-get update && apt-get install -y --no-install-recommends \
30+
ca-certificates \
31+
python \
32+
wget \
33+
&& \
34+
cd ~ && \
35+
wget -q https://nodejs.org/download/release/v$NODE_VER/node-v$NODE_VER-linux-$ARCH.tar.gz && \
36+
tar xf node-v$NODE_VER-linux-$ARCH.tar.gz && \
37+
rm node-v$NODE_VER-linux-$ARCH.tar.gz && \
38+
mv node-v$NODE_VER-linux-$ARCH /opt/node
2739

2840
# Install Ruby
2941
ENV RUBY_VER="2.7.2"
30-
RUN apt-get update && \
31-
apt-get install -y --no-install-recommends build-essential \
32-
bison libyaml-dev libgdbm-dev libreadline-dev libjemalloc-dev \
33-
libncurses5-dev libffi-dev zlib1g-dev libssl-dev && \
34-
cd ~ && \
35-
wget https://cache.ruby-lang.org/pub/ruby/${RUBY_VER%.*}/ruby-$RUBY_VER.tar.gz && \
36-
tar xf ruby-$RUBY_VER.tar.gz && \
37-
cd ruby-$RUBY_VER && \
38-
./configure --prefix=/opt/ruby \
39-
--with-jemalloc \
40-
--with-shared \
41-
--disable-install-doc && \
42-
make -j"$(nproc)" > /dev/null && \
43-
make install && \
44-
rm -rf ../ruby-$RUBY_VER.tar.gz ../ruby-$RUBY_VER
45-
46-
ENV PATH="${PATH}:/opt/ruby/bin:/opt/node/bin"
47-
48-
RUN npm install -g yarn && \
49-
gem install bundler && \
50-
apt-get update && \
51-
apt-get install -y --no-install-recommends git libicu-dev libidn11-dev \
52-
libpq-dev libprotobuf-dev protobuf-compiler shared-mime-info
53-
42+
RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \
43+
--mount=type=cache,sharing=locked,target=/var/lib/apt \
44+
apt-get update && apt-get install -y --no-install-recommends \
45+
bison \
46+
build-essential \
47+
libffi-dev \
48+
libgdbm-dev \
49+
libjemalloc-dev \
50+
libncurses5-dev \
51+
libreadline-dev \
52+
libssl-dev \
53+
libyaml-dev \
54+
zlib1g-dev \
55+
&& \
56+
cd ~ && \
57+
wget https://cache.ruby-lang.org/pub/ruby/${RUBY_VER%.*}/ruby-$RUBY_VER.tar.gz && \
58+
tar xf ruby-$RUBY_VER.tar.gz && rm ruby-$RUBY_VER.tar.gz && \
59+
cd ruby-$RUBY_VER && \
60+
./configure --prefix=/opt/ruby \
61+
--with-jemalloc \
62+
--with-shared \
63+
--disable-install-doc && \
64+
make -j"$(nproc)" > /dev/null && \
65+
make install && \
66+
rm -rf /root/ruby-$RUBY_VER
67+
68+
# Install packages needed for bundle install
69+
RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \
70+
--mount=type=cache,sharing=locked,target=/var/lib/apt \
71+
apt-get update && apt-get install -y --no-install-recommends \
72+
git \
73+
libicu-dev \
74+
libidn11-dev \
75+
libpq-dev \
76+
libprotobuf-dev \
77+
protobuf-compiler \
78+
shared-mime-info
79+
RUN npm install -g yarn
80+
RUN gem install bundler:1.17.2 --verbose
81+
82+
83+
FROM build-dep as prod-dep
84+
85+
# Install bundle and npm dependencies
5486
COPY Gemfile* package.json yarn.lock /opt/mastodon/
55-
5687
RUN cd /opt/mastodon && \
5788
bundle config set --local deployment 'true' && \
5889
bundle config set --local without 'development test' && \
59-
bundle install -j"$(nproc)" && \
60-
yarn install --pure-lockfile
90+
bundle install -j"$(nproc)" --deployment --without="development test" && \
91+
yarn install --pure-lockfile && \
92+
yarn cache clean && \
93+
rm -rf tmp
6194

62-
FROM ubuntu:20.04
95+
# Copy over mastodon source and compile assets
96+
COPY . /opt/mastodon/
97+
RUN cd /opt/mastodon && \
98+
RAILS_ENV=production OTP_SECRET=precompile_placeholder SECRET_KEY_BASE=precompile_placeholder \
99+
rails assets:precompile && \
100+
yarn cache clean && \
101+
rm -rf tmp
63102

64-
# Copy over all the langs needed for runtime
65-
COPY --from=build-dep /opt/node /opt/node
66-
COPY --from=build-dep /opt/ruby /opt/ruby
67103

68-
# Add more PATHs to the PATH
69-
ENV PATH="${PATH}:/opt/ruby/bin:/opt/node/bin:/opt/mastodon/bin"
104+
FROM ubuntu:20.04 as runtime-base
105+
106+
# Enable super fast apt caches for use with --mount=type=cache
107+
RUN rm -f /etc/apt/apt.conf.d/docker-clean; \
108+
echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
70109

71110
# Create the mastodon user
72111
ARG UID=991
73112
ARG GID=991
74113
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
75-
RUN apt-get update && \
76-
echo "Etc/UTC" > /etc/localtime && \
77-
apt-get install -y --no-install-recommends whois wget && \
78-
addgroup --gid $GID mastodon && \
79-
useradd -m -u $UID -g $GID -d /opt/mastodon mastodon && \
80-
echo "mastodon:$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 24 | mkpasswd -s -m sha-256)" | chpasswd && \
81-
rm -rf /var/lib/apt/lists/*
114+
ENV PATH="/opt/ruby/bin:/opt/node/bin:/opt/mastodon/bin:${PATH}"
82115

83116
# Install mastodon runtime deps
84-
RUN apt-get update && \
85-
apt-get -y --no-install-recommends install \
86-
libssl1.1 libpq5 imagemagick ffmpeg libjemalloc2 \
87-
libicu66 libprotobuf17 libidn11 libyaml-0-2 \
88-
file ca-certificates tzdata libreadline8 gcc tini && \
89-
ln -s /opt/mastodon /mastodon && \
90-
gem install bundler && \
91-
rm -rf /var/cache && \
92-
rm -rf /var/lib/apt/lists/*
93-
94-
# Copy over mastodon source, and dependencies from building, and set permissions
95-
COPY --chown=mastodon:mastodon . /opt/mastodon
96-
COPY --from=build-dep --chown=mastodon:mastodon /opt/mastodon /opt/mastodon
97-
98-
# Run mastodon services in prod mode
99-
ENV RAILS_ENV="production"
100-
ENV NODE_ENV="production"
117+
RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \
118+
--mount=type=cache,sharing=locked,target=/var/lib/apt \
119+
echo "Etc/UTC" > /etc/localtime && \
120+
apt-get update && apt-get -y --no-install-recommends install \
121+
ca-certificates \
122+
ffmpeg \
123+
file \
124+
imagemagick \
125+
libicu66 \
126+
libidn11 \
127+
libjemalloc2 \
128+
libpq5 \
129+
libprotobuf17 \
130+
libreadline8 \
131+
libssl1.1 \
132+
libyaml-0-2 \
133+
tini \
134+
tzdata \
135+
wget \
136+
whois \
137+
&& \
138+
addgroup --gid $GID mastodon && \
139+
useradd -m -u $UID -g $GID -d /opt/mastodon mastodon && \
140+
echo "mastodon:$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 24 | mkpasswd -s -m sha-256)" | chpasswd && \
141+
ln -s /opt/mastodon /mastodon
142+
143+
# Set the work dir and the container entry point
144+
WORKDIR /opt/mastodon
145+
ENTRYPOINT ["/usr/bin/tini", "--"]
146+
EXPOSE 3000 4000
147+
USER mastodon
101148

102149
# Tell rails to serve static files
103150
ENV RAILS_SERVE_STATIC_FILES="true"
104151
ENV BIND="0.0.0.0"
105152

106-
# Set the run user
153+
154+
FROM runtime-base as development
155+
COPY --from=build-dep /opt/node /opt/node
156+
COPY --from=build-dep /opt/ruby /opt/ruby
157+
158+
# Install everything we need to run a full bundle install
159+
USER root
160+
RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \
161+
--mount=type=cache,sharing=locked,target=/var/lib/apt \
162+
apt-get update && apt-get install -y --no-install-recommends \
163+
build-essential \
164+
git \
165+
libicu-dev \
166+
libidn11-dev \
167+
libjemalloc-dev \
168+
libpq-dev \
169+
libprotobuf-dev \
170+
libssl-dev \
171+
protobuf-compiler \
172+
shared-mime-info
107173
USER mastodon
108174

109-
# Precompile assets
110-
RUN cd ~ && \
111-
OTP_SECRET=precompile_placeholder SECRET_KEY_BASE=precompile_placeholder rails assets:precompile && \
112-
yarn cache clean
175+
# Run mastodon services in development mode
176+
ENV RAILS_ENV="development"
177+
ENV NODE_ENV="development"
178+
179+
180+
FROM runtime-base as production
181+
COPY --from=prod-dep /opt/node /opt/node
182+
COPY --from=prod-dep /opt/ruby /opt/ruby
183+
COPY --from=prod-dep --chown=mastodon:mastodon /opt/mastodon /opt/mastodon
184+
185+
# Run mastodon services in production mode
186+
ENV RAILS_ENV="production"
187+
ENV NODE_ENV="production"
188+
113189

114-
# Set the work dir and the container entry point
115-
WORKDIR /opt/mastodon
116-
ENTRYPOINT ["/usr/bin/tini", "--"]
117-
EXPOSE 3000 4000

‎Makefile

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
DOCKER_IMAGE_LOCAL ?= "hometown:local"
2+
DOCKER_IMAGE_PROD ?= "hometown:prod"
3+
DOCKER_PROJECT = $(shell basename "$$PWD")
4+
UNAME_S := $(shell uname -s)
5+
UID ?= "991"
6+
GID ?= "991"
7+
NPROC = 1
8+
9+
# Hide the annoying docker snyk ad
10+
export DOCKER_SCAN_SUGGEST=false
11+
12+
ifeq ($(UNAME_S),Linux)
13+
NPROC = $(shell nproc)
14+
UID=`id -u ${USER}`
15+
GID=`id -g ${USER}`
16+
endif
17+
ifeq ($(UNAME_S),Darwin)
18+
NPROC = $(shell sysctl -n hw.ncpu)
19+
endif
20+
21+
up:
22+
ifeq (,$(wildcard .docker-db-initialized))
23+
@echo "Database has not been initialized, running init script..."
24+
make init
25+
else
26+
make install
27+
docker-compose -f docker-compose.local.yml run --rm web rails db:migrate
28+
endif
29+
docker-compose -f docker-compose.local.yml up
30+
31+
init: install
32+
docker-compose -f docker-compose.local.yml run --rm sidekiq bash -c "\
33+
bundle exec rails db:environment:set RAILS_ENV=development &&\
34+
bundle exec rails db:setup RAILS_ENV=development &&\
35+
bundle exec rails db:migrate RAILS_ENV=development"
36+
docker-compose -f docker-compose.local.yml down
37+
touch .docker-db-initialized
38+
@echo "\nHometown initialization finished! You can now start all containers using: $ make up"
39+
40+
down:
41+
docker-compose -f docker-compose.local.yml down
42+
43+
clean:
44+
docker rm -f hometown-build
45+
docker buildx rm hometown || true
46+
docker-compose -f docker-compose.local.yml down
47+
docker volume rm -f $(DOCKER_PROJECT)_db $(DOCKER_PROJECT)_redis
48+
rm .docker-db-initialized
49+
50+
51+
install: build-development
52+
docker-compose -f docker-compose.local.yml down
53+
docker-compose -f docker-compose.local.yml up -d db
54+
docker-compose -f docker-compose.local.yml run --rm webpack bash -c "\
55+
bundle config set deployment 'true' && \
56+
bundle install -j$(NPROC) --deployment && \
57+
yarn install --pure-lockfile"
58+
59+
build-development:
60+
DOCKER_BUILDKIT=1 \
61+
docker build --target development \
62+
--build-arg UID=$(UID) \
63+
--build-arg GID=$(GID) \
64+
--tag $(DOCKER_IMAGE_LOCAL) .

‎README.md

+40-1
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,47 @@ Hometown uses [semantic versioning](https://semver.org) and follows a versioning
8484

8585
## Contributing to Hometown
8686

87-
Setting up your Hometown development environment is [exactly like setting up your Mastodon development environment](https://docs.joinmastodon.org/dev/overview/). Pull requests should be made to the `hometown-dev` branch, which is our default branch in Github.
87+
Pull requests should be made to the `hometown-dev` branch, which is our default branch in Github.
8888

89+
## Local development environment
90+
91+
Queer Haus comes with a preconfigured local environment using docker.
92+
93+
### Prerequisites
94+
1. Install make<br>
95+
Mac: `brew install make`<br>
96+
Ubuntu: `sudo apt install make`<br>
97+
Windows: https://stackoverflow.com/questions/32127524/how-to-install-and-use-make-in-windows
98+
99+
2. Install Docker<br>
100+
Ubuntu: https://docs.docker.com/engine/install/ubuntu/<br>
101+
Mac/Windows: https://www.docker.com/products/docker-desktop
102+
103+
3. Make sure that docker is correctly set up in your environment.
104+
This command should print an empty list of containers that are running:<br>
105+
`$ docker ps`<br>
106+
If that command gives you an error, resolve that using standard Docker guides _before continuing_.
107+
The command should not require sudo, if it does, your setup is not working correctly.
108+
109+
### Usage
110+
111+
1. Initialize the project and start the containers<br>
112+
`$ make up`<br>
113+
The first time this build can take up to 30 minutes depending on your machine.
114+
Wait until all services has started and webpack says it has compiled all resources.
115+
116+
2. Then you can access Queer Haus on http://localhost:3000
117+
118+
3. Press CTRL-C to stop the services.
119+
120+
4. To start it again next time, run the same command.
121+
Dependencies are updated and containers rebuilt as needed.<br>
122+
`$ make up`
123+
124+
5. Want to start over with a clean dev environment?
125+
Run 'clean' to stop everything and delete all databases.<br>
126+
`$ make clean`
127+
89128
## License
90129

91130
Copyright (C) 2016-2021 Eugen Rochko & other Mastodon contributors (see [AUTHORS.md](AUTHORS.md))

‎config/initializers/content_security_policy.rb

+3-1
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ def host_to_url(str)
2929

3030
if Rails.env.development?
3131
webpacker_urls = %w(ws http).map { |protocol| "#{protocol}#{Webpacker.dev_server.https? ? 's' : ''}://#{Webpacker.dev_server.host_with_port}" }
32+
# TODO: get these from webpack.yml config key: public
33+
webpacker_public_urls = 'http://localhost:3035', 'ws://localhost:3035'
3234

33-
p.connect_src :self, :data, :blob, assets_host, media_host, Rails.configuration.x.streaming_api_base_url, *webpacker_urls
35+
p.connect_src :self, :data, :blob, assets_host, media_host, Rails.configuration.x.streaming_api_base_url, *webpacker_urls, *webpacker_public_urls
3436
p.script_src :self, :unsafe_inline, :unsafe_eval, assets_host
3537
p.child_src :self, :blob, assets_host
3638
p.worker_src :self, :blob, assets_host

‎config/webpacker.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ development:
5555
# Reference: https://webpack.js.org/configuration/dev-server/
5656
dev_server:
5757
https: false
58-
host: localhost
58+
host: webpack
5959
port: 3035
6060
public: localhost:3035
6161
hmr: false

‎docker-compose.local.yml

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
version: '3.5'
2+
# This docker setup is for local development and NOT intended for production use!
3+
4+
volumes:
5+
db:
6+
redis:
7+
8+
services:
9+
10+
db:
11+
restart: unless-stopped
12+
image: postgres:9.6-alpine
13+
shm_size: 256mb
14+
healthcheck:
15+
test: ["CMD", "pg_isready", "-U", "mastodon"]
16+
volumes:
17+
- db:/var/lib/postgresql/data
18+
environment:
19+
# Disable authentication https://www.postgresql.org/docs/current/auth-trust.html
20+
POSTGRES_HOST_AUTH_METHOD: trust
21+
POSTGRES_USER: mastodon
22+
POSTGRES_PASSWORD: mastodon
23+
24+
redis:
25+
restart: unless-stopped
26+
image: redis:6.0-alpine
27+
healthcheck:
28+
test: ["CMD", "redis-cli", "ping"]
29+
volumes:
30+
- redis:/data
31+
32+
web:
33+
build:
34+
context: .
35+
target: development
36+
image: hometown:local
37+
restart: unless-stopped
38+
env_file: .env.docker
39+
command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -b 0.0.0.0 -p 3000"
40+
healthcheck:
41+
test: ["CMD-SHELL", "wget -q --spider --proxy=off localhost:3000/health || exit 1"]
42+
ports:
43+
- "127.0.0.1:3000:3000"
44+
depends_on:
45+
- db
46+
- redis
47+
- webpack
48+
# - es
49+
volumes:
50+
- .:/mastodon:delegated
51+
52+
webpack:
53+
build:
54+
context: .
55+
target: development
56+
image: hometown:local
57+
restart: unless-stopped
58+
env_file: .env.docker
59+
command: ./bin/webpack-dev-server --listen-host 0.0.0.0
60+
ports:
61+
- "127.0.0.1:3035:3035"
62+
volumes:
63+
- .:/mastodon:delegated
64+
65+
streaming:
66+
build:
67+
context: .
68+
target: development
69+
image: hometown:local
70+
restart: unless-stopped
71+
env_file: .env.docker
72+
command: node ./streaming
73+
healthcheck:
74+
test: ["CMD-SHELL", "wget -q --spider --proxy=off localhost:4000/api/v1/streaming/health || exit 1"]
75+
ports:
76+
- "127.0.0.1:4000:4000"
77+
depends_on:
78+
- db
79+
- redis
80+
volumes:
81+
- .:/mastodon:delegated
82+
83+
sidekiq:
84+
build:
85+
context: .
86+
target: development
87+
image: hometown:local
88+
restart: unless-stopped
89+
env_file: .env.docker
90+
command: bundle exec sidekiq
91+
depends_on:
92+
- db
93+
- redis
94+
volumes:
95+
- .:/mastodon:delegated

‎docker-compose.yml

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
version: '3'
2+
# This docker setup is an example file for production use
3+
24
services:
35

46
db:

0 commit comments

Comments
 (0)
Please sign in to comment.