##// END OF EJS Templates
docker: add Docker files for running an Apache mod_wsgi server...
Gregory Szorc -
r23399:fd5247a8 default
parent child Browse files
Show More
@@ -0,0 +1,23 b''
1 FROM debian:wheezy
2
3 ENV DEBIAN_FRONTEND noninteractive
4 ENV WSGI_PROCESSES 4
5 ENV WSGI_THREADS 1
6 ENV WSGI_MAX_REQUESTS 100000
7
8 EXPOSE 80
9 VOLUME ["/var/hg/htdocs", "/var/hg/repos"]
10
11 RUN apt-get update && apt-get -y install libapache2-mod-wsgi python-dev vim
12
13 # Install our own Apache site.
14 RUN a2dissite 000-default
15 ADD vhost.conf /etc/apache2/sites-available/hg
16 RUN a2ensite hg
17
18 ADD hgwebconfig /defaulthgwebconfig
19
20 ADD entrypoint.sh /entrypoint.sh
21 ENTRYPOINT ["/entrypoint.sh"]
22
23 CMD ["/usr/sbin/apache2", "-DFOREGROUND"]
@@ -0,0 +1,144 b''
1 ====================
2 Apache Docker Server
3 ====================
4
5 This directory contains code for running a Mercurial hgweb server via
6 mod_wsgi with the Apache HTTP Server inside a Docker container.
7
8 .. important::
9
10 This container is intended for testing purposes only: it is
11 **not** meant to be suitable for production use.
12
13 Building Image
14 ==============
15
16 The first step is to build a Docker image containing Apache and mod_wsgi::
17
18 $ docker build -t hg-apache .
19
20 .. important::
21
22 You should rebuild the image whenever the content of this directory
23 changes. Rebuilding after pulling or when you haven't run the container
24 in a while is typically a good idea.
25
26 Running the Server
27 ==================
28
29 To run the container, you'll execute something like::
30
31 $ docker run --rm -it -v `pwd`/../../..:/var/hg/source -p 8000:80 hg-apache
32
33 If you aren't a Docker expert:
34
35 * ``--rm`` will remove the container when it stops (so it doesn't clutter
36 your system)
37 * ``-i`` will launch the container in interactive mode so stdin is attached
38 * ``-t`` will allocate a pseudo TTY
39 * ``-v src:dst`` will mount the host filesystem at ``src`` into ``dst``
40 in the container. In our example, we assume you are running from this
41 directory and use the source code a few directories up.
42 * ``-p 8000:80`` will publish port ``80`` on the container to port ``8000``
43 on the host, allowing you to access the HTTP server on the host interface.
44 * ``hg-apache`` is the container image to run. This should correspond to what
45 we build with ``docker build``.
46
47 .. important::
48
49 The container **requires** that ``/var/hg/source`` contain the Mercurial
50 source code.
51
52 Upon start, the container will attempt an install of the source in that
53 directory. If the architecture of the host machine doesn't match that of
54 the Docker host (e.g. when running Boot2Docker under OS X), Mercurial's
55 Python C extensions will fail to run. Be sure to ``make clean`` your
56 host's source tree before mounting it in the container to avoid this.
57
58 When starting the container, you should see some start-up actions (including
59 a Mercurial install) and some output saying Apache has started::
60
61 Now if you load ``http://localhost:8000/`` (or whatever interface Docker
62 is using), you should see hgweb running!
63
64 For your convenience, we've created an empty repository available at
65 ``/repo``. Feel free to populate it with ``hg push``.
66
67 Customizing the Server
68 ======================
69
70 By default, the Docker container installs a basic hgweb config and an
71 empty dummy repository. It also uses some reasonable defaults for
72 mod_wsgi.
73
74 Customizing the WSGI Dispatcher And Mercurial Config
75 ----------------------------------------------------
76
77 By default, the Docker environment installs a custom ``hgweb.wsgi``
78 file (based on the example in ``contrib/hgweb.wsgi``). The file
79 is installed into ``/var/hg/htdocs/hgweb.wsgi``.
80
81 A default hgweb configuration file is also installed. The ``hgwebconfig``
82 file from this directory is installed into ``/var/hg/htdocs/config``.
83
84 You have a few options for customizing these files.
85
86 The simplest is to hack up ``hgwebconfig`` and ``entrypoint.sh`` in
87 this directory and to rebuild the Docker image. This has the downside
88 that the Mercurial working copy is modified and you may accidentally
89 commit unwanted changes.
90
91 The next simplest is to copy this directory somewhere, make your changes,
92 then rebuild the image. No working copy changes involved.
93
94 The preferred solution is to mount a host file into the container and
95 overwrite the built-in defaults.
96
97 For example, say we create a custom hgweb config file in ``~/hgweb``. We
98 can start the container like so to install our custom config file::
99
100 $ docker run -v ~/hgweb:/var/hg/htdocs/config ...
101
102 You can do something similar to install a custom WSGI dispatcher::
103
104 $ docker run -v ~/hgweb.wsgi:/var/hg/htdocs/hgweb.wsgi ...
105
106 Managing Repositories
107 ---------------------
108
109 Repositories are served from ``/var/hg/repos`` by default. This directory
110 is configured as a Docker volume. This means you can mount an existing
111 data volume container in the container so repository data is persisted
112 across container invocations. See
113 https://docs.docker.com/userguide/dockervolumes/ for more.
114
115 Alternatively, if you just want to perform lightweight repository
116 manipulation, open a shell in the container::
117
118 $ docker exec -it <container> /bin/bash
119
120 Then run ``hg init``, etc to manipulate the repositories in ``/var/hg/repos``.
121
122 mod_wsgi Configuration Settings
123 -------------------------------
124
125 mod_wsgi settings can be controlled with the following environment
126 variables.
127
128 WSGI_PROCESSES
129 Number of WSGI processes to run.
130 WSGI_THREADS
131 Number of threads to run in each WSGI process
132 WSGI_MAX_REQUESTS
133 Maximum number of requests each WSGI process may serve before it is
134 reaped.
135
136 See https://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIDaemonProcess
137 for more on these settings.
138
139 .. note::
140
141 The default is to use 1 thread per process. The reason is that Mercurial
142 doesn't perform well in multi-threaded mode due to the GIL. Most people
143 run a single thread per process in production for this reason, so that's
144 what we default to.
@@ -0,0 +1,80 b''
1 #!/bin/bash
2
3 # This script gets executed on container start. Its job is to set up
4 # the Mercurial environment and invoke the server.
5
6 # Mercurial can be started in two modes.
7 # If the MERCURIAL_SOURCE environment variable is set and it points to a
8 # Mercurial source directory, we will install Mercurial from that directory.
9 # Otherwise, we download the Mercurial source and install it manually.
10
11 set -e
12
13 SOURCE_DIR=/var/hg/source
14 INSTALL_DIR=/var/hg/install
15 REPOS_DIR=/var/hg/repos
16 HTDOCS_DIR=/var/hg/htdocs
17
18 if [ ! -d ${SOURCE_DIR} ]; then
19 echo "Mercurial source not available at ${SOURCE_DIR}"
20 echo "You need to mount a volume containing the Mercurial source code"
21 echo "when running the container. For example:"
22 echo ""
23 echo " $ docker run -v ~/src/hg:/${SOURCE_DIR} hg-apache"
24 echo ""
25 echo "This container will now stop running."
26 exit 1
27 fi
28
29 echo "Installing Mercurial from ${SOURCE_DIR} into ${INSTALL_DIR}"
30 pushd ${SOURCE_DIR}
31 /usr/bin/python2.7 setup.py install --root=/ --prefix=${INSTALL_DIR} --force
32 popd
33
34 mkdir -p ${HTDOCS_DIR}
35
36 # Provide a default config if the user hasn't supplied one.
37 if [ ! -f ${HTDOCS_DIR}/config ]; then
38 cp /defaulthgwebconfig ${HTDOCS_DIR}/config
39 fi
40
41 if [ ! -f ${HTDOCS_DIR}/hgweb.wsgi ]; then
42 cat >> ${HTDOCS_DIR}/hgweb.wsgi << EOF
43 config = '${HTDOCS_DIR}/config'
44
45 import sys
46 sys.path.insert(0, '${INSTALL_DIR}/lib/python2.7/site-packages')
47
48 from mercurial import demandimport
49 demandimport.enable()
50
51 from mercurial.hgweb import hgweb
52 application = hgweb(config)
53 EOF
54 fi
55
56 mkdir -p ${REPOS_DIR}
57
58 if [ ! -d ${REPOS_DIR}/repo ]; then
59 ${INSTALL_DIR}/bin/hg init ${REPOS_DIR}/repo
60 chown -R www-data:www-data ${REPOS_DIR}/repo
61 fi
62
63 # This is necessary to make debuginstall happy.
64 if [ ! -f ~/.hgrc ]; then
65 cat >> ~/.hgrc << EOF
66 [ui]
67 username = Dummy User <nobody@example.com>
68 EOF
69 fi
70
71 echo "Verifying Mercurial installation looks happy"
72 ${INSTALL_DIR}/bin/hg debuginstall
73
74 . /etc/apache2/envvars
75
76 echo "Starting Apache HTTP Server on port 80"
77 echo "We hope you remembered to publish this port when running the container!"
78 echo "If this is an interactive container, simply CTRL^C to stop."
79
80 exec "$@"
@@ -0,0 +1,6 b''
1 [paths]
2 / = /var/hg/repos/*
3
4 [web]
5 allow_push = *
6 push_ssl = False
@@ -0,0 +1,24 b''
1 # Apache won't be able to resolve its own hostname, so we sneak this
2 # into the global context to silence a confusing-to-user warning on
3 # server start.
4 ServerName hg
5
6 <VirtualHost *:80>
7 DocumentRoot /var/hg/htdocs
8 <Directory />
9 Options FollowSymLinks
10 AllowOverride None
11 </Directory>
12
13 SetEnv HGENCODING UTF-8
14 SetEnv LC_TYPE UTF-8
15
16 WSGIDaemonProcess hg processes=${WSGI_PROCESSES} threads=${WSGI_THREADS} maximum-requests=${WSGI_MAX_REQUESTS} user=www-data group=www-data display-name=hg-wsgi
17 WSGIProcessGroup hg
18
19 WSGIScriptAliasMatch ^(.*) /var/hg/htdocs/hgweb.wsgi$1
20
21 ErrorLog ${APACHE_LOG_DIR}/error.log
22 LogLevel warn
23 CustomLog ${APACHE_LOG_DIR}/access.log combined
24 </VirtualHost>
General Comments 0
You need to be logged in to leave comments. Login now