Skip to content

Commit a7b7a2a

Browse files
committed
Move requirements.txt bit out of 9 and into 10
1 parent c02cb23 commit a7b7a2a

File tree

4 files changed

+264
-167
lines changed

4 files changed

+264
-167
lines changed

chapter_09_docker.asciidoc

Lines changed: 31 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -703,94 +703,18 @@ environment?
703703
Ah, we forgot that we need to install Django.
704704
705705
706-
=== Virtualenv and requirements.txt
707-
708-
// TODO: move to next chapter
706+
=== Installing Django into our Virtualenv
709707
710708
Just like on our own machine,
711709
a virtualenv is useful in a deployed environment to make
712710
sure we have full control over the packages installed for a particular
713711
project.
714712
715-
To reproduce our local virtualenv,
716-
rather than just manually pip installing things
717-
one by one, and having to remember to sync things
718-
between local dev and docker,
719-
we can "save" the list of packages we're using
720-
by creating a 'requirements.txt' file.footnote:[
721-
There are many other dependency management tools these days
722-
so requirements.txt is not the only way to do it,
723-
although it is one of the oldest and best established.
724-
As you continue your Python adventures
725-
I'm sure you'll come across many others.]
726-
727-
728-
[subs="specialcharacters,quotes"]
729-
----
730-
$ *pip freeze*
731-
asgiref==3.7.2
732-
attrs==23.1.0
733-
certifi==2023.7.22
734-
Django==4.2.7
735-
h11==0.14.0
736-
idna==3.4
737-
outcome==1.3.0.post0
738-
PySocks==1.7.1
739-
selenium==4.15.2
740-
sniffio==1.3.0
741-
sortedcontainers==2.4.0
742-
sqlparse==0.4.4
743-
trio==0.23.1
744-
trio-websocket==0.11.1
745-
urllib3==2.1.0
746-
wsproto==1.2.0
747-
----
748-
749-
That shows _all_ the packages in our virtualenv. Let's find Django,
750-
and then add it as a single item to our requirements.txt,
751-
with its exact version specified:
752-
753-
754-
//004
755-
[subs="specialcharacters,quotes"]
756-
----
757-
$ *pip freeze | grep -i django*
758-
Django==4.2.7
759-
$ *pip freeze | grep -i django== >> requirements.txt*
760-
# that's a good first cut, let's commit it:
761-
$ *git add requirements.txt*
762-
$ *git commit -m "Add requirements.txt for virtualenv"*
763-
----
764-
765-
You may be wondering why we didn't add our other dependency,
766-
Selenium, to our requirements,
767-
or why we didn't just add _all_ the dependencies,
768-
including the "transitive" ones (eg, Django has its own dependencies of `asgiref` and `sqlparse`).
769-
770-
As always, I have to gloss over some nuance and tradeoffs,
771-
but the short answer is first, Selenium is only a dependency for the tests,
772-
not the application code;
773-
we're never going to run the tests directly on our production servers.
774-
As to transitive dependencies, they're fiddly to manage without bringing
775-
in more tools, and I didn't want to do that for this book.footnote:[
776-
When you have a moment, you might want to do some further reading
777-
on "lockfiles", pyproject.toml, hard pinning vs soft pining,
778-
and immediate vs transitive dependencies. If I absolutely _had_
779-
to recommend a python dependency management tool,
780-
it would be https://github.com/jazzband/pip-tools[pip-tools],
781-
which is a fairly minimal one.]
782-
783-
784-
TIP: Itamar Turner-Traurig has a great guide to
785-
https://pythonspeed.com/docker/[Docker Packaging for Python Developers],
786-
which I cannot recommend highly enough. Read that before you're too much older.
787-
788-
In any case, back in our Dockerfile, we can create a virtualenv
713+
We can create a virtualenv in our Dockerfile
789714
just like we did on our own machine with `python -m venv`,
790-
and then we can use the special `-r` flag for `pip install`,
791-
to point it at our requirements file:
715+
and then we can use `pip install` to get Django:
792716
793-
.Dockerfile (ch09l005)
717+
.Dockerfile (ch09l004)
794718
====
795719
[source,dockerfile]
796720
----
@@ -799,8 +723,7 @@ FROM python:slim
799723
RUN python -m venv /venv <1>
800724
ENV PATH="/venv/bin:$PATH" <2>
801725
802-
COPY requirements.txt requirements.txt <3>
803-
RUN pip install -r requirements.txt <4>
726+
RUN pip install "django<5" <3>
804727
805728
COPY src /src
806729
@@ -817,17 +740,8 @@ CMD python manage.py runserver
817740
of `pip` and `python` become the default ones
818741
(this is actually one of the things that `activate` does, under the hood).
819742
820-
<3> We copy our requirements file in, just like the src folder.
821-
822-
<4> Now we install our dependencies with `pip`,
823-
pointing it at our _requirements.txt_.
824-
Notice the `-r`.
743+
<3> We install Django with `pip install`, just like we do locally.
825744
826-
TIP: Forgetting the `-r` and running `pip install requirements.txt`
827-
is such a common error, that I recommend you do it _right now_
828-
and get familiar with the error message
829-
(which is thankfully much more helpful than it used to be).
830-
It's a mistake I still make, _all the time_.
831745
832746
833747
==== Successful Run
@@ -846,14 +760,13 @@ $ *docker build -t superlists . && docker run -it superlists*
846760
=> [internal] load build definition from Dockerfile 0.0s
847761
=> => transferring dockerfile: 246B 0.0s
848762
=> [internal] load metadata for docker.io/library/python:slim 0.0s
849-
=> CACHED [1/6] FROM docker.io/library/python:slim 0.0s
763+
=> CACHED [1/5] FROM docker.io/library/python:slim 0.0s
850764
=> [internal] load build context 0.0s
851765
=> => transferring context: 4.75kB 0.0s
852-
=> [2/6] RUN python -m venv /venv 0.0s
853-
=> [3/6] COPY requirements.txt requirements.txt 0.0s
854-
=> [4/6] RUN pip install -r requirements.txt 0.0s
855-
=> [5/6] COPY src /src 0.0s
856-
=> [6/6] WORKDIR /src 0.0s
766+
=> [2/5] RUN python -m venv /venv 0.0s
767+
=> [3/5] pip install "django<5" 0.0s
768+
=> [4/5] COPY src /src 0.0s
769+
=> [5/5] WORKDIR /src 0.0s
857770
=> exporting to image 0.0s
858771
=> => exporting layers 0.0s
859772
=> => writing image sha256:[...] 0.0s
@@ -959,7 +872,7 @@ that we specified in the `TEST_SERVER` env var.
959872
Let's fix that by amending the `CMD` instruction in the Dockerfile:
960873
961874
962-
.Dockerfile (ch09l006)
875+
.Dockerfile (ch09l005)
963876
====
964877
[source,dockerfile]
965878
----
@@ -1393,11 +1306,9 @@ CMD python manage.py runserver
13931306
----
13941307
====
13951308
1396-
The extra flag to add is `--mount`,
1397-
where we specify `type=bind`, the `source` path on our machine,
1398-
and the `target` path _inside_ the container:
1309+
Let's start by re-creating the database with `migrate`
1310+
(when we moved everything into `./src`, we left the database file behind):
13991311
1400-
[role="small-code"]
14011312
[subs="specialcharacters,quotes"]
14021313
----
14031314
$ *./src/manage.py migrate --noinput*
@@ -1407,20 +1318,33 @@ Running migrations:
14071318
Applying contenttypes.0001_initial... OK
14081319
[...]
14091320
Applying sessions.0001_initial... OK
1321+
----
1322+
1323+
Let's make sure to .gitignore the new location of the DB file:
1324+
1325+
[subs="specialcharacters,quotes"]
1326+
----
1327+
$ *echo src/db.sqlite3 >> .gitignore*
1328+
----
1329+
1330+
Now let's try mounting our database file.
1331+
The extra flag to add to the Docker run command is `--mount`,
1332+
where we specify `type=bind`, the `source` path on our machine,
1333+
and the `target` path _inside_ the container:
1334+
1335+
[subs="specialcharacters,quotes"]
1336+
----
14101337
$ *docker build -t superlists . && docker run \
14111338
-p 8888:8888 \
14121339
--mount type=bind,source=./src/db.sqlite3,target=/src/db.sqlite3 \
14131340
-it superlists*
14141341
----
14151342
1416-
// TODO: db.sqlite3 will actually be missing at this point because we did *not* mv it earlier
1417-
14181343
TIP: The old syntax for mounts was `-v`.
14191344
One of the advantages of the new `--mount` syntax is that it will fail hard
14201345
if the path you're trying to mount into the container does not exist
14211346
(it says something like `bind source path does not exist`)
1422-
This avoids a lot of pain, ask me how I now this.
1423-
1347+
This avoids a lot of pain, ask me how I know this.
14241348
14251349
14261350
And we check the FTs again.

0 commit comments

Comments
 (0)