Skip to content

Commit c2609f5

Browse files
authored
Merge pull request #6418 from readthedocs/humitos/docker-tasks
inv tasks to use when developing with docker
2 parents f20832c + 1dbe225 commit c2609f5

25 files changed

+169
-31
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,6 @@ env.bak/
6767
venv.bak/
6868

6969
dev.db-journal
70+
/readthedocs/settings/build.py
71+
/readthedocs/settings/celery.py
72+
/readthedocs/settings/web.py

docker-compose-search.yml

+3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ services:
2424
- storage
2525
- azure-cli
2626
- search
27+
environment:
28+
- DJANGO_SETTINGS_MODULE=readthedocs.settings.celery
29+
- SEARCH=t
2730

2831
# You may need to increase the memory for vm
2932
# sudo sysctl -w vm.max_map_count=262144

docker-compose.yml

+18-16
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ services:
1717
# Image used for all the other services (proxito, web, celery, build)
1818
build:
1919
context: .
20-
dockerfile: ${PWD}/docker/Dockerfile
20+
dockerfile: ${PWD}/dockerfiles/Dockerfile
2121

2222
nginx:
2323
image: nginx
@@ -28,16 +28,16 @@ services:
2828
- proxito
2929
- storage
3030
volumes:
31-
- ${PWD}/docker/nginx:/etc/nginx/conf.d
31+
- ${PWD}/dockerfiles/nginx:/etc/nginx/conf.d
3232

3333
proxito:
3434
image: readthedocsorg_server:latest
3535
volumes:
36-
- ${PWD}/docker/entrypoints/common.sh:/usr/src/app/docker/common.sh
37-
- ${PWD}/docker/entrypoints/proxito.sh:/usr/src/app/docker/proxito.sh
36+
- ${PWD}/dockerfiles/entrypoints/common.sh:/usr/src/app/docker/common.sh
37+
- ${PWD}/dockerfiles/entrypoints/proxito.sh:/usr/src/app/docker/proxito.sh
3838
- ${PWD}:/usr/src/app/checkouts/readthedocs.org
3939
- ${PWD}/../readthedocs-ext:/usr/src/app/checkouts/readthedocs-ext
40-
- ${PWD}/docker/settings/proxito.py:/usr/src/app/checkouts/readthedocs.org/readthedocs/settings/proxito.py
40+
- ${PWD}/dockerfiles/settings/proxito.py:/usr/src/app/checkouts/readthedocs.org/readthedocs/settings/proxito.py
4141
links:
4242
- storage
4343
- database
@@ -55,12 +55,12 @@ services:
5555
web:
5656
image: readthedocsorg_server:latest
5757
volumes:
58-
- ${PWD}/docker/scripts/createsuperuser.py:/usr/src/app/docker/createsuperuser.py
59-
- ${PWD}/docker/entrypoints/common.sh:/usr/src/app/docker/common.sh
60-
- ${PWD}/docker/entrypoints/web.sh:/usr/src/app/docker/web.sh
58+
- ${PWD}/dockerfiles/scripts/createsuperuser.py:/usr/src/app/docker/createsuperuser.py
59+
- ${PWD}/dockerfiles/entrypoints/common.sh:/usr/src/app/docker/common.sh
60+
- ${PWD}/dockerfiles/entrypoints/web.sh:/usr/src/app/docker/web.sh
6161
- ${PWD}/../readthedocs-ext:/usr/src/app/checkouts/readthedocs-ext
6262
- ${PWD}:/usr/src/app/checkouts/readthedocs.org
63-
- ${PWD}/docker/settings/web.py:/usr/src/app/checkouts/readthedocs.org/readthedocs/settings/web.py
63+
- ${PWD}/dockerfiles/settings/web.py:/usr/src/app/checkouts/readthedocs.org/readthedocs/settings/web.py
6464
links:
6565
- storage
6666
- database
@@ -69,6 +69,7 @@ services:
6969
- storage
7070
- azure-cli
7171
environment:
72+
- INIT=${INIT}
7273
- DJANGO_SETTINGS_MODULE=readthedocs.settings.web
7374
stdin_open: true
7475
tty: true
@@ -77,11 +78,12 @@ services:
7778
celery:
7879
image: readthedocsorg_server:latest
7980
volumes:
80-
- ${PWD}/docker/entrypoints/common.sh:/usr/src/app/docker/common.sh
81-
- ${PWD}/docker/entrypoints/celery.sh:/usr/src/app/docker/celery.sh
81+
- ${PWD}/dockerfiles/entrypoints/common.sh:/usr/src/app/docker/common.sh
82+
- ${PWD}/dockerfiles/entrypoints/celery.sh:/usr/src/app/docker/celery.sh
83+
- ${PWD}/dockerfiles/scripts/wait_for_search.py:/usr/src/app/docker/scripts/wait_for_search.py
8284
- ${PWD}/../readthedocs-ext:/usr/src/app/checkouts/readthedocs-ext
8385
- ${PWD}:/usr/src/app/checkouts/readthedocs.org
84-
- ${PWD}/docker/settings/celery.py:/usr/src/app/checkouts/readthedocs.org/readthedocs/settings/celery.py
86+
- ${PWD}/dockerfiles/settings/celery.py:/usr/src/app/checkouts/readthedocs.org/readthedocs/settings/celery.py
8587
links:
8688
- storage
8789
- database
@@ -98,11 +100,11 @@ services:
98100
build:
99101
image: readthedocsorg_server:latest
100102
volumes:
101-
- ${PWD}/docker/entrypoints/common.sh:/usr/src/app/docker/common.sh
102-
- ${PWD}/docker/entrypoints/build.sh:/usr/src/app/docker/build.sh
103+
- ${PWD}/dockerfiles/entrypoints/common.sh:/usr/src/app/docker/common.sh
104+
- ${PWD}/dockerfiles/entrypoints/build.sh:/usr/src/app/docker/build.sh
103105
- ${PWD}/../readthedocs-ext:/usr/src/app/checkouts/readthedocs-ext
104106
- ${PWD}:/usr/src/app/checkouts/readthedocs.org
105-
- ${PWD}/docker/settings/build.py:/usr/src/app/checkouts/readthedocs.org/readthedocs/settings/build.py
107+
- ${PWD}/dockerfiles/settings/build.py:/usr/src/app/checkouts/readthedocs.org/readthedocs/settings/build.py
106108

107109
# The python code at readthedocs/doc_builder/environments.py
108110
# mounts `self.project.doc_path`. We need to share this path
@@ -134,7 +136,7 @@ services:
134136
azure-cli:
135137
image: microsoft/azure-cli
136138
volumes:
137-
- ${PWD}/docker/scripts/create-containers.sh:/usr/local/bin/create-containers.sh
139+
- ${PWD}/dockerfiles/scripts/create-containers.sh:/usr/local/bin/create-containers.sh
138140
links:
139141
- storage
140142
depends_on:

docker/entrypoints/web.sh

-13
This file was deleted.

docker/Dockerfile renamed to dockerfiles/Dockerfile

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
FROM ubuntu:18.04
22

33
ENV DEBIAN_FRONTEND noninteractive
4-
ENV LANG C.UTF-8
4+
ENV LANG en_US.UTF-8
5+
ENV LANGUAGE en_US:en
6+
ENV LC_ALL en_US.UTF-8
57

68
WORKDIR /usr/src/app
79

@@ -14,6 +16,7 @@ RUN apt-get -y install \
1416
libpq-dev \
1517
libxml2-dev \
1618
libxslt1-dev \
19+
locales \
1720
build-essential \
1821
python3-pip \
1922
python3-dev \
@@ -23,6 +26,10 @@ RUN apt-get -y install \
2326
libjpeg-dev \
2427
sqlite
2528

29+
# Uncomment en_US.UTF-8 locale and generate it
30+
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
31+
locale-gen
32+
2633
RUN pip3 install --no-cache-dir --upgrade pip
2734

2835
RUN mkdir checkouts
File renamed without changes.
File renamed without changes.

docker/entrypoints/celery.sh renamed to dockerfiles/entrypoints/celery.sh

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
../../docker/common.sh
44

5+
python3 ../../docker/scripts/wait_for_search.py
6+
57
watchmedo auto-restart \
68
--patterns="*.py" \
79
--ignore-patterns="*.#*.py;./user_builds/*;./public_*;./private_*;*.pyo;*.pyc;*flycheck*.py;./media/*;./.tox/*" \
File renamed without changes.
File renamed without changes.

dockerfiles/entrypoints/web.sh

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#! /bin/sh
2+
3+
../../docker/common.sh
4+
5+
if [ -n "$INIT" ];
6+
then
7+
echo "Performing initial tasks..."
8+
python3 manage.py migrate
9+
cat ../../docker/createsuperuser.py | python3 manage.py shell
10+
python3 manage.py collectstatic --no-input
11+
python3 manage.py loaddata test_data
12+
fi
13+
14+
python3 manage.py runserver 0.0.0.0:8000
File renamed without changes.
File renamed without changes.
File renamed without changes.
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import os
2+
import time
3+
import requests
4+
5+
wait_sleep = 3
6+
max_loops = 15
7+
8+
loops = 1
9+
if 'SEARCH' in os.environ:
10+
while loops < max_loops:
11+
try:
12+
print('Waiting for search service...')
13+
response = requests.get('http://search:9200/_cluster/health')
14+
if response.status_code == 200:
15+
print('Search is ready!')
16+
break
17+
loops += 1
18+
except:
19+
pass
20+
time.sleep(wait_sleep)
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

dockerfiles/tasks.py

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
from invoke import task
2+
3+
DOCKER_COMPOSE = 'docker-compose.yml'
4+
DOCKER_COMPOSE_SEARCH = 'docker-compose-search.yml'
5+
DOCKER_COMPOSE_COMMAND = f'docker-compose -f {DOCKER_COMPOSE} -f {DOCKER_COMPOSE_SEARCH}'
6+
7+
@task
8+
def build(c):
9+
"""Build docker image for servers."""
10+
c.run(f'{DOCKER_COMPOSE_COMMAND} build --no-cache', pty=True)
11+
12+
@task
13+
def down(c, volumes=False):
14+
"""Stop and remove all the docker containers."""
15+
if volumes:
16+
c.run(f'{DOCKER_COMPOSE_COMMAND} down -v', pty=True)
17+
else:
18+
c.run(f'{DOCKER_COMPOSE_COMMAND} down', pty=True)
19+
20+
@task
21+
def up(c, no_search=False, init=False):
22+
"""Start all the docker containers for a Read the Docs instance"""
23+
INIT = ''
24+
if init:
25+
INIT = 'INIT=t'
26+
27+
if no_search:
28+
c.run(f'{INIT} docker-compose -f {DOCKER_COMPOSE} up', pty=True)
29+
else:
30+
c.run(f'{INIT} {DOCKER_COMPOSE_COMMAND} up', pty=True)
31+
32+
@task
33+
def shell(c, running=False, container='web'):
34+
"""Run a shell inside a container."""
35+
if running:
36+
c.run(f'{DOCKER_COMPOSE_COMMAND} exec {container} /bin/bash', pty=True)
37+
else:
38+
c.run(f'{DOCKER_COMPOSE_COMMAND} run --rm {container} /bin/bash', pty=True)
39+
40+
@task
41+
def manage(c, command):
42+
"""Run manage.py with a specific command."""
43+
c.run(f'{DOCKER_COMPOSE_COMMAND} run --rm web python3 manage.py {command}', pty=True)
44+
45+
@task
46+
def attach(c, container):
47+
"""Attach a tty to a running container (useful for pdb)."""
48+
c.run(f'docker attach readthedocsorg_{container}_1', pty=True)
49+
50+
@task
51+
def restart(c, containers):
52+
"""Restart one or more containers."""
53+
c.run(f'{DOCKER_COMPOSE_COMMAND} restart {containers}', pty=True)
54+
55+
# When restarting a container that nginx is connected to, we need to restart
56+
# nginx as well because it has the IP cached
57+
need_nginx_restart = [
58+
'web',
59+
'proxito'
60+
'storage',
61+
]
62+
for extra in need_nginx_restart:
63+
if extra in containers:
64+
c.run(f'{DOCKER_COMPOSE_COMMAND} restart nginx', pty=True)
65+
break
66+
67+
@task
68+
def pull(c):
69+
"""Pull all docker images required for build servers."""
70+
images = [
71+
('4.0', 'stable'),
72+
('5.0', 'latest'),
73+
]
74+
for image, tag in images:
75+
c.run(f'docker pull readthedocs/build:{image}', pty=True)
76+
c.run(f'docker tag readthedocs/build:{image} readthedocs/build:{tag}', pty=True)
77+
78+
@task
79+
def test(c, arguments=''):
80+
"""Run all test suite."""
81+
c.run(f'{DOCKER_COMPOSE_COMMAND} run --rm --no-deps web tox {arguments}', pty=True)

readthedocs/settings/docker_compose.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class DockerBaseSettings(CommunityDevSettings):
2424
MULTIPLE_BUILD_SERVERS = ['build']
2525

2626
# Enable auto syncing elasticsearch documents
27-
ELASTICSEARCH_DSL_AUTOSYNC = True
27+
ELASTICSEARCH_DSL_AUTOSYNC = True if 'SEARCH' in os.environ else False
2828
ELASTICSEARCH_DSL = {
2929
'default': {
3030
'hosts': 'search:9200',

requirements/docker.txt

+3
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,6 @@ watchdog==0.9.0
1111
datadiff==2.0.0
1212
ipdb==0.12.2
1313
pdbpp==0.10.2
14+
15+
# run tests
16+
tox==3.14.1

tasks.py

+16
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from invoke import task, Collection
88

99
import common.tasks
10+
import dockerfiles.tasks
1011

1112

1213
ROOT_PATH = os.path.dirname(__file__)
@@ -35,6 +36,21 @@
3536
name='packages',
3637
)
3738

39+
namespace.add_collection(
40+
Collection(
41+
dockerfiles.tasks.build,
42+
dockerfiles.tasks.down,
43+
dockerfiles.tasks.up,
44+
dockerfiles.tasks.shell,
45+
dockerfiles.tasks.manage,
46+
dockerfiles.tasks.attach,
47+
dockerfiles.tasks.restart,
48+
dockerfiles.tasks.pull,
49+
dockerfiles.tasks.test,
50+
),
51+
name='docker',
52+
)
53+
3854
# Localization tasks
3955
@task
4056
def push(ctx):

0 commit comments

Comments
 (0)