Skip to content

Commit e1875d4

Browse files
committed
add documentation on docker deployment
1 parent 49653fd commit e1875d4

File tree

1 file changed

+320
-1
lines changed

1 file changed

+320
-1
lines changed

deployment/docker/index.md

Lines changed: 320 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,323 @@ description: Tutorial on how to deploy Fano application with Docker container.
55

66
<h1 class="major">Deploy Fano application inside Docker container</h1>
77

8-
[Back to Deployment](/deployment)
8+
## Prerequisite
9+
10+
You have working Docker and Docker Compose installation.
11+
12+
Your current user is in group `docker`. If you are not in `docker` group, you will have to prefix all docker command with sudo.
13+
14+
## Deploy Fano CGI Application with Docker
15+
16+
### Create Dockerfile
17+
Create file name `Dockerfile` in project root directory with content like so
18+
19+
```
20+
FROM httpd:2.4
21+
```
22+
23+
This tells Docker to create container image based Apache 2.4. This is Debian-based image with common Apache modules are installed.
24+
25+
Now append lines below. We make sure that `mod_cgi`, `mod_cgid` and `mod_rewrite` modules are loaded by modifying main Apache configuration like so.
26+
27+
```
28+
RUN sed -i \
29+
-e 's/^#\(LoadModule .*mod_cgi.so\)/\1/' \
30+
-e 's/^#\(LoadModule .*mod_cgid.so\)/\1/' \
31+
-e 's/^#\(LoadModule .*mod_rewrite.so\)/\1/' \
32+
-e 's/^#\(Include .*httpd-vhosts.conf\)/\1/' \
33+
-e 's/^#ServerName.*/ServerName fano-app/' \
34+
/usr/local/apache2/conf/httpd.conf
35+
```
36+
37+
In case unclear to you, regular expressions replace `#LoadModule mod_cgi` to become `LoadModule mod_cgi` effectively tells Apache to load `mod_cgi`.
38+
39+
We also tells Apache to include any additional configurations in `httpd-vhosts.conf` file and set `ServerName` configuration.
40+
41+
42+
Append line below to copy `vhost.example` file to `httpd-vhosts.conf` inside container. We will create `vhost.example` latter.
43+
44+
```
45+
COPY ./vhost.example /usr/local/apache2/conf/extra/httpd-vhosts.conf
46+
```
47+
48+
Remove `index.html` as we do not need it, but this is optional step.
49+
```
50+
RUN rm /usr/local/apache2/htdocs/index.html
51+
```
52+
53+
Now add below it
54+
```
55+
COPY ./config/ /usr/local/apache2/config
56+
COPY ./resources/ /usr/local/apache2/resources
57+
COPY ./storages/ /usr/local/apache2/storages
58+
COPY ./public/ /usr/local/apache2/htdocs/
59+
COPY ./public/app.cgi /usr/local/apache2/htdocs/app.cgi
60+
61+
```
62+
Which copy all runtime files needed by application such as configuration, HTML templates, CSS and JavaScript files.
63+
64+
So final Dockerfile will be
65+
66+
```
67+
FROM httpd:2.4
68+
69+
RUN sed -i \
70+
-e 's/^#\(LoadModule .*mod_cgi.so\)/\1/' \
71+
-e 's/^#\(LoadModule .*mod_cgid.so\)/\1/' \
72+
-e 's/^#\(LoadModule .*mod_rewrite.so\)/\1/' \
73+
-e 's/^#\(Include .*httpd-vhosts.conf\)/\1/' \
74+
-e 's/^#ServerName.*/ServerName fano-app/' \
75+
/usr/local/apache2/conf/httpd.conf
76+
77+
COPY ./vhost.example /usr/local/apache2/conf/extra/httpd-vhosts.conf
78+
79+
RUN rm /usr/local/apache2/htdocs/index.html
80+
81+
COPY ./config/ /usr/local/apache2/config
82+
COPY ./resources/ /usr/local/apache2/resources
83+
COPY ./storages/ /usr/local/apache2/storages
84+
COPY ./public/ /usr/local/apache2/htdocs/
85+
COPY ./public/app.cgi /usr/local/apache2/htdocs/app.cgi
86+
```
87+
88+
### Create virtual host configuration
89+
90+
Create a file name `vhost.example` in same directory as `Dockerfile` with content like so
91+
92+
```
93+
<VirtualHost *:80>
94+
<Directory "/usr/local/apache2/htdocs">
95+
Options +ExecCGI
96+
AllowOverride FileInfo Indexes
97+
Require all granted
98+
DirectoryIndex app.cgi
99+
AddHandler cgi-script .cgi
100+
<IfModule mod_rewrite.c>
101+
RewriteEngine On
102+
103+
RewriteCond %{REQUEST_FILENAME} !-d
104+
RewriteCond %{REQUEST_FILENAME} !-f
105+
RewriteRule ^(.*)$ app.cgi [L]
106+
</IfModule>
107+
</Directory>
108+
</VirtualHost>
109+
```
110+
111+
### Run application in Docker container
112+
113+
Run `build.sh` to compile application first and then from inside directory where Dockerfile resides, run
114+
115+
```
116+
$ docker build -t fano-app .
117+
```
118+
119+
This will build docker image with tag `fano-app` and may take a while.
120+
121+
After that run
122+
123+
```
124+
$ docker run fano-app
125+
```
126+
127+
Open Internet browser and go to `http://172.17.0.2` to access application.
128+
129+
### Run with docker-compose
130+
131+
We can take it further by using `docker-compose` to run application. Create new file name `docker-compose.yaml` in same directory as `Dockerfile`.
132+
133+
```
134+
version: "2"
135+
services:
136+
fano:
137+
build: .
138+
```
139+
140+
Now we can run with
141+
142+
```
143+
$ docker-compose up
144+
```
145+
146+
## Deploy Fano FastCGI Application with Docker
147+
148+
### Create Dockerfile
149+
150+
If you create FastCGI project using `--project-fcgid`
151+
152+
```
153+
$ fanocli --project-fcgid=testfano
154+
```
155+
156+
To deploy using Docker, we need to install `mod_fcgid` manually. This module is not installed by default in `httpd:2.4` image.
157+
158+
```
159+
FROM:home:24
160+
161+
#-----------------------------------
162+
# Install mod_fcgid
163+
#-----------------------------------
164+
RUN apt-get update && \
165+
apt-get install -y --no-install-recommends \
166+
libapache2-mod-fcgid
167+
```
168+
Following `mod_fcgid` installation, we tells Apache to load module.
169+
170+
```
171+
#-----------------------------------
172+
# Enable mod_fcgid mod_rewrite and
173+
# additional virtual host config
174+
#-----------------------------------
175+
RUN sed -i \
176+
-e 's/^#\(LoadModule .*mod_rewrite.so\)/\1/' \
177+
-e 's/^#\(Include .*httpd-vhosts.conf\)/\1/' \
178+
-e '/LoadModule .*mod_rewrite.so/a LoadModule fcgid_module /usr/lib/apache2/modules/mod_fcgid.so' \
179+
-e 's/^#ServerName.*/ServerName fano-app/' \
180+
/usr/local/apache2/conf/httpd.conf
181+
182+
```
183+
184+
The rest of Dockerfile is same as Dockerfile for CGI above.
185+
186+
## Deploy Fano FastCGI Application with Docker
187+
188+
### Create Dockerfile
189+
For FastCGI that runs as separate server via reverse-proxy module, i.e, using `--project-fcgi`, you can run Fano application and Apache as separate docker container and run it with `docker-compose`.
190+
191+
```
192+
$ fanocli --project-fcgi=testfano
193+
```
194+
195+
For that we need to create two Dockerfiles for Fano application and Apache.
196+
197+
### Dockerfile for Fano application
198+
199+
Dockerfile for Fano application is just pull Ubuntu image and copy binary executable, configuration file, HTML templates etc.
200+
201+
Last, we tells Docker to execute application and listen on `0.0.0.0:7704`. Parameter `--host=0.0.0.0` is required, otherwise our application will only listen on `127.0.0.1`. Because Apache will act as reverse-proxy server on different container, it will not be able to connect to Fano application without `--host=0.0.0.0`.
202+
203+
```
204+
FROM ubuntu
205+
206+
COPY ./config/ /usr/local/fano/config
207+
COPY ./resources/ /usr/local/fano/resources
208+
COPY ./bin/app.cgi /usr/local/fano/app.cgi
209+
CMD ["/usr/local/fano/app.cgi", "--host=0.0.0.0", "--port=7704"]
210+
```
211+
We name this Dockerfile as `fano_dockerfile`.
212+
213+
### Dockerfile for Apache reverse proxy server
214+
215+
Dockerfile for Apache mostly similar to above Dockerfile for CGI but with goal to setup Apache as FastCGI reverse proxy server that connect to our application. This is done by tells Apache to load `mod_proxy` and `mod_proxy_fcgi`.
216+
217+
```
218+
FROM httpd:2.4
219+
220+
#-----------------------------------
221+
# Enable mod_proxy_fcgi mod_rewrite and
222+
# additional virtual host config
223+
#-----------------------------------
224+
RUN sed -i \
225+
-e 's/^#\(LoadModule .*mod_proxy.so\)/\1/' \
226+
-e 's/^#\(LoadModule .*mod_proxy_fcgi.so\)/\1/' \
227+
-e 's/^#\(LoadModule .*mod_rewrite.so\)/\1/' \
228+
-e 's/^#\(Include .*httpd-vhosts.conf\)/\1/' \
229+
-e 's/^#ServerName.*/ServerName fano-app/' \
230+
/usr/local/apache2/conf/httpd.conf && \
231+
rm /usr/local/apache2/htdocs/index.html
232+
233+
#-----------------------------------
234+
# set default virtual host config
235+
#-----------------------------------
236+
COPY ./vhost.example /usr/local/apache2/conf/extra/httpd-vhosts.conf
237+
238+
#-----------------------------------
239+
# copy public assets (images, css, js)
240+
#-----------------------------------
241+
COPY ./public/ /usr/local/apache2/htdocs
242+
243+
```
244+
245+
We copy `vhost.example` into container virtual host configuraton. We will create it latter.
246+
247+
We name this Dockerfile as `httpd_dockerfile`.
248+
249+
### Create virtual host configuration
250+
We create new file `vhost.example` with content aim to setup FastCGI reverse proxy. `fcgi://fano:7704` line tells Apache to forward FastCGI data to our application container identified as `fano` (This is service we defined in `docker-compose.yaml` below).
251+
252+
```
253+
<VirtualHost *:80>
254+
ProxyRequests Off
255+
ProxyPassMatch "/css|js|images|img|plugins|bower_components(.*)|webfonts" !
256+
ProxyPassMatch ^/(.*)$ "fcgi://fano:7704"
257+
</VirtualHost>
258+
```
259+
260+
### Create docker-compose configuration.
261+
262+
To simplify running both application, we use docker-compose with configuration like so
263+
264+
```
265+
version: "2"
266+
services:
267+
fano:
268+
build:
269+
context: .
270+
dockerfile: fano_dockerfile
271+
ports:
272+
- "7704:7704"
273+
apache:
274+
build:
275+
context: .
276+
dockerfile: httpd_dockerfile
277+
depends_on:
278+
- fano
279+
```
280+
281+
Here we tells docker-compose to build two services from two dockerfiles we previously created. We also forward traffic on port `7704` so that Apache container can connect it.
282+
283+
Do not forget to save it as `docker-compose.yaml`.
284+
285+
### Run FastCGI application with docker-compose
286+
287+
To run application and Apache, run build.sh script first and then,
288+
289+
```
290+
$ docker-compose up
291+
```
292+
293+
To access application, we need to get IP address of Apache container image.
294+
Run
295+
296+
```
297+
$ docker network ls
298+
```
299+
300+
It will list all Docker available networks. If our application is in `testfano` directory,
301+
it will be listed as `testfano_default` by default. To get IP address
302+
303+
```
304+
$ docker network inspect testfano_default
305+
```
306+
307+
Find IP address for Apache, for example if it prints `172.20.0.3/16`
308+
Then open browser and visit `http://172.20.0.3` to access our application.
309+
310+
## Deploy Fano SCGI Application with Docker
311+
312+
This will mostly similar to FastCGI reverse proxy setup above, except that `httpd_dockerfile` will load `mod_proxy_scgi` and `vhost.example` contains `scgi://fano:7704` line
313+
314+
## Deploy Fano uwsgi Application with Docker
315+
316+
This will mostly similar to FastCGI reverse proxy setup above, except that `httpd_dockerfile` will load `mod_proxy_uwsgi` and `vhost.example` contains `uwsgi://fano:7704` line
317+
318+
## Deploy Fano CLI-generated Project with Docker
319+
320+
[Fano CLI](/scaffolding-with-fano-cli/) since `v1.13.0` generates `docker-compose.yaml` file during creation of [CGI](/scaffolding-with-fano-cli/creating-project/#scaffolding-cgi-project), [FastCGI](/scaffolding-with-fano-cli/creating-project/#scaffolding-fcgid-project), [SCGI](/scaffolding-with-fano-cli/creating-project/#scaffolding-scgi-project) and [uwsgi](/scaffolding-with-fano-cli/creating-project/#scaffolding-uwsgi-project) project.
321+
322+
Which means you can skip steps above and just compile application and then run with `docker-compose up`.
323+
324+
## Explore more
325+
326+
- [Scaffolding with Fano CLI](/scaffolding-with-fano-cli/)
327+
- [Deployment](/deployment)

0 commit comments

Comments
 (0)