@@ -57,32 +57,44 @@ an ORM, all sorts of middleware, the admin site...
57
57
"What else do you want, a pony?" Well, Gunicorn stands for "Green Unicorn",
58
58
which I guess is what you'd want next if you already had a pony...
59
59
60
+ //001
61
+ cmdg
62
+
63
+
64
+ [subs="specialcharacters,quotes"]
60
65
----
61
- pip install gunicorn
62
- pip freeze | grep -i gunicorn== >> requirements.txt
66
+ $ *pip install gunicorn*
67
+ Collecting gunicorn
68
+ [...]
69
+ Successfully installed gunicorn-21.2.0
70
+ $ *pip freeze | grep -i gunicorn== >> requirements.txt*
63
71
----
64
72
65
73
Gunicorn will need to know a path to a WSGI server,
66
74
which is usually a function called `application`.
67
75
Django provides one in 'superlists/wsgi.py':
68
76
77
+ [role="sourcecode"]
78
+ .Dockerfile (ch10l002)
79
+ ====
80
+ [source,Dockerfile]
69
81
----
70
- CMD [" gunicorn", " --bind", " :8888", " superlists.wsgi:application"]
82
+ CMD gunicorn --bind :8888 superlists.wsgi:application
71
83
----
72
-
73
- // TODO mention new cmd syntax with ["list"]
74
-
84
+ ====
75
85
76
86
As in the previous chapter, we can use the `docker build && docker run`
77
87
pattern to try out our changes by rebuilding and rerunning our container:
78
88
89
+ [subs="specialcharacters,quotes"]
79
90
----
80
91
$ *docker build -t superlists . && docker run \
81
92
-p 8888:8888 \
82
93
-v ./src/db.sqlite3:/src/db.sqlite3 \
83
94
-it superlists*
84
95
----
85
96
97
+
86
98
==== The FTs catch a problem with static files
87
99
88
100
As we run the functional tests, you'll see them warning us of a problem, once again.
@@ -101,7 +113,7 @@ FAILED (failures=1)
101
113
And indeed, if you take a look at the site, you'll find the CSS is all broken,
102
114
as in <<site-with-broken-css>>.
103
115
104
- The reason that the CSS is broken is that although the Django dev server will
116
+ The reason that we have no CSS is that although the Django dev server will
105
117
serve static files magically for you, Gunicorn doesn't.
106
118
107
119
170
182
171
183
Phew. Let's commit that
172
184
185
+ [subs="specialcharacters,quotes"]
173
186
----
174
- *git commit -am"Switch to Gunicorn and Whitenoise"*
187
+ $ *git commit -am"Switch to Gunicorn and Whitenoise"*
175
188
----
176
189
177
190
@@ -182,12 +195,6 @@ We know there are several things in
182
195
_settings.py_ that we want to change for production:
183
196
184
197
185
- ////
186
- * +ALLOWED_HOSTS+ is currently set to "*" which isn't secure. We want it
187
- to be set to only match the site we're supposed to be serving
188
- (_localhost_ for now, but someday soon, a real domain).
189
- ////
190
-
191
198
* `DEBUG` mode is all very well for hacking about on your own server,
192
199
but it https://docs.djangoproject.com/en/1.11/ref/settings/#debug[isn't secure].
193
200
For example, exposing raw tracebacks to the world is a bad idea.
@@ -205,7 +212,7 @@ Development, staging and production sites always have some differences
205
212
in their configuration.
206
213
Environment variables are a good place to store those different settings.
207
214
See http://www.clearlytech.com/2014/01/04/12-factor-apps-plain-english/[
208
- "the 12-factor app "].footnote:[
215
+ "The 12-Factor App "].footnote:[
209
216
Another common way of handling this
210
217
is to have different versions of _settings.py_ for dev and prod.
211
218
That can work fine too, but it can get confusing to manage.
@@ -269,31 +276,34 @@ Now let's set that environment variable in our Dockerfile using then `ENV` direc
269
276
WORKDIR /src
270
277
271
278
ENV DJANGO_DEBUG_FALSE=1
272
- CMD [" gunicorn", " --bind", " :8888", " superlists.wsgi:application"]
279
+ CMD gunicorn --bind :8888 superlists.wsgi:application
273
280
----
274
281
====
275
282
276
283
And try it out...
277
284
278
285
279
286
287
+ [subs="specialcharacters,macros"]
280
288
----
281
- $ *docker build -t superlists . && docker run \
289
+ $ pass:quotes[ *docker build -t superlists . && docker run \
282
290
-p 8888:8888 \
283
291
-v ./src/db.sqlite3:/src/db.sqlite3 \
284
- -it superlists*
292
+ -it superlists*]
285
293
286
294
[...]
295
+ File "/src/superlists/settings.py", line 22, in <module>
287
296
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
288
297
~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
289
- # TODO: show more of traceback
298
+ File "<frozen os>", line 685, in __getitem__
299
+ KeyError: 'DJANGO_SECRET_KEY'
290
300
----
291
301
292
302
Ooops, and I forgot to set said secret key env var,
293
303
mere seconds after having dreamt it up!
294
304
295
305
296
- ==== Setting environment variables at the docker command-line
306
+ ==== Setting Environment Variables at the Docker Command Line
297
307
298
308
We've said we can't keep the secret key in our source code,
299
309
so the Dockerfile isn't an option; where else can we put it?
@@ -427,7 +437,7 @@ WORKDIR /src
427
437
RUN python manage.py collectstatic
428
438
429
439
ENV DJANGO_DEBUG_FALSE=1
430
- CMD [" gunicorn", " --bind", " :8888", " superlists.wsgi:application"]
440
+ CMD gunicorn --bind :8888 superlists.wsgi:application
431
441
----
432
442
====
433
443
444
454
445
455
We have a container that we're ready to ship to production!
446
456
447
- Find out how in the next exciting installment.
457
+ Find out how in the next exciting installment...
448
458
449
459
460
+ ////
450
461
=== TODO: log files
451
462
452
- provoke a 500 error somehow and make sure we see tracebacks for it
463
+ provoke a 500 error somehow and make sure we see tracebacks for it?
464
+
465
+ docker logs might be enough.
466
+ alternatively, mount logfiles from host.
467
+ ////
453
468
454
469
455
470
[role="pagebreak-before less_space"]
@@ -469,7 +484,7 @@ Decide how to serve your static files::
469
484
that comes from Django and your webapp, so they need to be treated differently.
470
485
WhiteNoise is just one example of how you might do that.
471
486
472
- Check your settings.py for dev-only settings ::
487
+ Check your settings.py for dev-only config ::
473
488
`DEBUG=True`, `ALLOWED_HOSTS` and `SECRET_KEY` are the ones we came across,
474
489
but you will probably have others
475
490
(we'll see more when we start to send emails from the server).
@@ -480,21 +495,5 @@ Change things one at a time and rerun your tests frequently::
480
495
and either be confident that everything works as well as it did before,
481
496
or find out immediately if we did something wrong.
482
497
483
- Security::
484
- A serious discussion of server security is beyond the scope of this book,
485
- and I'd warn against running your own servers
486
- without learning a good bit more about it.
487
- (One reason people choose to use a PaaS to host their code
488
- is that it means a slightly fewer security issues to worry about.)
489
- If you'd like a place to start, here's as good a place as any:
490
- https://plusbryan.com/my-first-5-minutes-on-a-server-or-essential-security-for-linux-servers[My first 5 minutes on a server].
491
- I can definitely recommend the eye-opening experience of installing
492
- fail2ban and watching its logfiles to see just how quickly it picks up on
493
- random drive-by attempts to brute force your SSH login. The internet is a
494
- wild place!
495
- ((("security issues and settings", "server security")))
496
- ((("Platform-As-A-Service (PaaS)")))
497
-
498
- TODO: that last one probably belongs in the next chapter.
499
498
500
499
*******************************************************************************
0 commit comments