This document provides an overview of developing applications in Docker. It defines key Docker terminology like Dockerfile, image, and container. It demonstrates how to build an image from a Dockerfile, run containers, and use Dockerfiles to package applications. Tips are given for optimizing images like using lightweight base images, combining commands, and removing temporary files. Volumes are demonstrated as a way to share files between the host and container during development.
2. YipitData is not endorsed by, directly affiliated with, maintained,
authorized, or sponsored by Docker Inc.
Disclaimer
3.
4. ● Brief terminology
● Running containers
● Dockerfiles & Images
● Tips for development
General Outline
5. ● Dockerfile: Defines the instructions to create an image
● Image: An executable package that contains the resources
needed to run a container
● Container: The result (a process) of executing an image. A
new container is made each time an image is executed
Dockerfile, Images, Containers, .. ?
6. ● An easy way to create a container is by using “docker run”
docker run -it --rm <IMAGE:TAG> <COMMAND>
● Example:
docker run -it --rm python:3.6.5-jessie python
OK, but how do I even container ?
7. ● An easy way to create a container is by using “docker run”
docker run -it --rm <IMAGE:TAG> <COMMAND>
OK, but how do I even container ?
Exposes STDIN to the container and
emulates a terminal session. It lets you run
commands within the container
8. ● An easy way to create a container is by using “docker run”
docker run -it --rm <IMAGE:TAG> <COMMAND>
OK, but how do I even container ?
Deletes the container after you exit
the process, helps keep disk space
under control
9. ● There is no concept of “SSH” in docker. But you can access a
shell in a running container using docker exec:
docker exec -it <CONTAINER ID> bash
● You can find the container ID by running:
docker ps
So what about SSH ..
11. ● Exec is helpful during development to debug a container’s state
● When debugging production, you should try to recreate the
error using a fresh container locally
○ Exec is not supported in production
○ “Show Docker CLI” in YAWS is your friend
○ Enable logging to see more details
Don’t exec unless you have to.
12.
13. Check out this sweet Dockerfile ..
FROM python:3.6.7-jessie
COPY app /app
RUN pip install Flask
EXPOSE 8000
CMD ["python", "/app/__init__.py"]
14. FROM python:3.6.7-jessie
COPY app /app
RUN pip install Flask
EXPOSE 8000
CMD ["python", "/app/__init__.py"]
Check out this sweet Dockerfile ..
FROM loads a published
image as a starting point for
your application
15. FROM python:3.6.7-jessie
COPY app /app
RUN pip install Flask
EXPOSE 8000
CMD ["python", "/app/__init__.py"]
Check out this sweet Dockerfile ..
COPY takes files in the host file system
and moves them into the image
16. FROM python:3.6.7-jessie
COPY app /app
RUN pip install Flask
EXPOSE 8000
CMD ["python", "/app/__init__.py"]
Check out this sweet Dockerfile ..
RUN allows you to execute
commands inside the image
17. EXPOSE defines a
port that can be
accessed outside of
the container
FROM python:3.6.7-jessie
COPY app /app
RUN pip install Flask
EXPOSE 8000
CMD ["python", "/app/__init__.py"]
Check out this sweet Dockerfile ..
18. FROM python:3.6.7-jessie
COPY app /app
RUN pip install Flask
EXPOSE 8000
CMD ["python", "/app/__init__.py"]
Check out this sweet Dockerfile ..
CMD defines a
default command
the container will
run
19. docker build -t <NAME>:<TAG> <PATH>
“docker build” translates a Dockerfile into an image
20. docker build -t <NAME>:<TAG> <PATH>
Important to tag a readable
name for your image
“docker build” translates a Dockerfile into an image
21. docker build -t <NAME>:<TAG> <PATH>
Specifying a version will pin
changes of the images you
create
“docker build” translates a Dockerfile into an image
22. docker build -t <NAME>:<TAG> <PATH>
Path to your Dockerfile
and application code
“docker build” translates a Dockerfile into an image
23. ● Each instruction is a
layer, a change in the
image state
● Only FROM, RUN, and
COPY create layers
● The R/W layer is created
when running a container
An image is a series of “layers”
24. ● Ephemeral: Containers are created / destroyed with ease, and
any setup is handled by the image
● Few in Layers: More layers lead to larger image size and longer
build time
● Ordered for caching: The instructions in the Dockerfile are
sequenced to leverage caching. Least likely to change or
longest running instructions should be higher up
The best Dockerfiles are:
26. ● Base images can have unnecessary packages installed that
inflate your image size
FROM python:3.6.7-slim-jessie (157 MB)
FROM python:3.6.7-jessie (691 MB)
● Use a versioned base image, or your image will be built on the
latest base image (unstable)
Use the right base image
27. ● A common technique is to chain shell commands using the &&
operator
RUN apt-get update
RUN apt-get install -y cron
vs.
RUN apt-get update
&& apt-get install -y cron
Combine layers as much as possible
28. ● Linux by default will install many “recommended” packages you
do not need. You can disable this behavior:
RUN apt-get update
&& apt-get install -y --no-install-recommends
cron
Install only what you need
29. ● Packages may have extraneous files once installed, best
practice is to remove them
RUN curl s3://yipit/my_pkg.deb > my_pkg.deb
&& dpkg -i my_pkg.deb
&& rm -rf my_pkg.deb
Delete temporary files after installation
30. ● The demo images were small to begin with, production image
sizes can decrease 60 - 70%
Significant reductions in image size
31. Absolute file path in the host
machine you want to mount
● Volumes mount external (host) files to a container
● You can continue to modify these files and your running
container will be up to date
docker run --rm -it -v <HOST PATH:CONTAINER PATH>
<IMAGE:TAG>
Use volumes to speed up app development
32. ● Volumes mount external (host) files to a container
● You can continue to modify these files and your running
container will be up to date
docker run --rm -it -v <HOST PATH:CONTAINER PATH>
<IMAGE:TAG>
Destination file path in the
container for the mounted file(s)
Use volumes to speed up app development
34. ● Two ways to set variables in the Dockerfile, ARG and ENV
● ARG defines a build-time variable that is out of scope once the
image is built
○ Good for secrets only used in setup (ex: localshop)
● ENV sets an environment variable that is in scope during and
after the image is built
Environment variables
35. ● Both variables can be set via the CLI. They will override values
in the Dockerfile
● ARG:
docker build --build-arg <NAME=VALUE> -t
<IMAGE:TAG> .
● ENV:
docker run --rm -it -e <NAME=VALUE> <IMAGE:TAG>
Environment variables in the CLI
36. ● You will want to end your Dockerfile with a CMD and/or
ENTRYPOINT (or inherit from your base image)
● An ENTRYPOINT executes code right at a container’s runtime
○ Establish background processes / services
○ Wrap additional context around commands
○ A CMD is passed as an argument to the entrypoint
CMD or ENTRYPOINT?
38. ● Docker is a large platform and there is so much more to learn
● Best ways to get started:
○ Documentation: https://docs.docker.com/
○ Read Dockerfiles for base images (usually on github)
○ Build some images!
Tip of the iceberg ..
39. ● Containers improves parity of local development to production
○ The image you build is the image you deploy
○ Far easier to reproduce bugs
● Increases flexibility in your application architecture
○ OS packages easier to manage (no need for brew or chef)
○ Python versioning is simplified (no virtualenv)
But it pays off !
41. ● Official Docker Documentation
● Best Practices for Writing Dockerfiles
● Docker Container Layers
● XKCD on Containers
● XKCD on Compiling
References