{"id":113,"date":"2018-09-27T16:38:00","date_gmt":"2018-09-27T16:38:00","guid":{"rendered":"https:\/\/159.69.80.24\/blog\/what-is-docker-and-how-to-use-it-with-python\/"},"modified":"2025-09-11T16:48:02","modified_gmt":"2025-09-11T16:48:02","slug":"what-is-docker-and-how-to-use-it-with-python","status":"publish","type":"post","link":"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/","title":{"rendered":"Docker Tutorial: Using Docker with Python"},"content":{"rendered":"<p>This is an introductory Python Docker tutorial. By the end of this article, you will know how to use Docker on your local machine. Along with Python, we are going to run Nginx and Redis containers. Those examples assume that you are familiar with the basic concepts of those technologies. There will be lots of shell examples, so go ahead, open the terminal and explore our Docker with Python tutorial.<\/p>\n<article class=\"text-token-text-primary w-full focus:outline-none scroll-mt-[calc(var(--header-height)+min(200px,max(70px,20svh)))]\" dir=\"auto\" tabindex=\"-1\" data-turn-id=\"5eff7d11-35c0-4ed6-a6c3-2114ec750e22\" data-testid=\"conversation-turn-86\" data-scroll-anchor=\"true\" data-turn=\"assistant\">\n<div class=\"text-base my-auto mx-auto pb-10 [--thread-content-margin:--spacing(4)] thread-sm:[--thread-content-margin:--spacing(6)] thread-lg:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)\">\n<div class=\"[--thread-content-max-width:40rem] thread-sm:[--thread-content-max-width:40rem] thread-lg:[--thread-content-max-width:48rem] mx-auto max-w-(--thread-content-max-width) flex-1 group\/turn-messages focus-visible:outline-hidden relative flex w-full min-w-0 flex-col agent-turn\" tabindex=\"-1\">\n<div class=\"flex max-w-full flex-col grow\">\n<div class=\"min-h-8 text-message relative flex w-full flex-col items-end gap-2 text-start break-words whitespace-normal [.text-message+&amp;]:mt-5\" dir=\"auto\" data-message-author-role=\"assistant\" data-message-id=\"a2fa5dfd-7652-443a-bf1d-0ebb9037288f\" data-message-model-slug=\"gpt-5-thinking\">\n<div class=\"flex w-full flex-col gap-1 empty:hidden first:pt-[3px]\">\n<div class=\"markdown prose dark:prose-invert w-full break-words light markdown-new-styling\">\n<p data-start=\"540\" data-end=\"720\" data-is-last-node=\"\">After contributing a hands-on guide to <a href=\"https:\/\/djangostars.com\/blog\/python-descriptors\/\">descriptors Python<\/a>, our team is tackling this one. With the help of Docker and Python, we developed projects such as Money Park, Switzerland&#8217;s largest online mortgage broker, Billion To One, a US-based healthcare company providing genetic testing, Boa Lingua, the largest platform for language travel in Switzerland, and many others.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/article>\n<h2>What is Docker?<\/h2>\n<p><a href=\"https:\/\/www.docker.com\/\" target=\"_blank\" rel=\"nofollow noopener\">Docker<\/a> is an open-source tool that automates the deployment of an application inside a software container. The easiest way to grasp the idea behind Docker is to compare it to, well&#8230; standard shipping containers.<\/p>\n<p>Back in the day, transportation companies faced the following challenges:<\/p>\n<ul>\n<li>How to transport different (incompatible) types of goods side by side (like food and chemicals, or glass and bricks).<\/li>\n<li>How to handle packages of various sizes using the same vehicle.<\/li>\n<\/ul>\n<p>After the introduction of containers, bricks could be put over glass, and chemicals could be stored next to food. Cargo of various sizes can be put inside a standardized container and loaded\/unloaded by the same vehicle. Using Docker with Python is one of the most popular option in software development.<br \/>\n<div class=\"info_box_shortcode_holder\" style=\"background-image: url(https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2023\/08\/Web-Development_2.png)\">\n    <div class=\"info_box_label\">\n    Services\n    <\/div>\n    <div class=\"info_box_logo\">\n    \n    <\/div>\n    \n    <div class=\"info_box_title font_size_\">\n   <span class=\"info_box_title_inner\">Elevate your web development.&lt;br \/&gt;\n<\/span>\n    <\/div>\n    <div class=\"info_box_link\">\n        <a href=\"https:\/\/djangostars.com\/services\/web-development\/\" target=\"_blank\" >\n            <span>Learn More<\/span>\n            <div class=\"button_animated\">\n                <svg width=\"24\" height=\"12\" viewBox=\"0 0 24 12\" fill=\"none\"\n                     xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                    <path d=\"M23.725 5.33638C23.7248 5.3361 23.7245 5.33577 23.7242 5.33549L18.8256 0.460497C18.4586 0.0952939 17.865 0.096653 17.4997 0.463684C17.1345 0.830668 17.1359 1.42425 17.5028 1.7895L20.7918 5.06249H0.9375C0.419719 5.06249 0 5.48221 0 5.99999C0 6.51777 0.419719 6.93749 0.9375 6.93749H20.7917L17.5029 10.2105C17.1359 10.5757 17.1345 11.1693 17.4998 11.5363C17.865 11.9034 18.4587 11.9046 18.8256 11.5395L23.7242 6.66449C23.7245 6.66421 23.7248 6.66388 23.7251 6.6636C24.0923 6.29713 24.0911 5.70163 23.725 5.33638Z\"\n                          fill=\"#282828\"><\/path>\n                <\/svg>\n                <div class=\"shape\"><\/div>\n            <\/div>\n        <\/a>\n    <\/div>\n<\/div><br \/>\nLet\u2019s go back to software development\u00a0in Python using Docker containers.<\/p>\n<p>When you develop an application, you need to provide your code along with all possible dependencies like libraries, the web server, databases, etc. You may end up in a situation when the application is working on your computer, but won\u2019t even start on the staging server, or the dev or QA\u2019s machine.<\/p>\n<p>This challenge can be addressed by isolating the app to make it independent of the system.<\/p>\n<h2>How does this differ from virtualization?<\/h2>\n<p>Traditionally, virtual machines were used to avoid this unexpected behavior. The main problem with VM is that an \u201cextra OS\u201d on top of the host operating system adds gigabytes of space to the project. Most of the time your server will host several VMs that will take up even more space. And by the way, at the moment, most cloud-based server providers will charge you for that extra space. Another significant drawback of VM is a slow boot as, in addition, it runs identical processes that use CPU resources.<\/p>\n<p>Docker eliminates all the above by simply sharing the OS kernel across all the containers running as separate processes of the host OS.<\/p>\n<p>The diagram below shows how this looks with a Docker example.<br \/>\n<img decoding=\"async\" class=\"alignnone size-full wp-image-491\" src=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2018\/12\/Img-1-1-10.png\" alt=\"docker img\" width=\"1600\" height=\"1206\" \/><br \/>\nKeep in mind that Docker is not the first and not the only containerization platform. However, at the moment Docker is the biggest and the most powerful player on the market.<\/p>\n<h2>Why do we need Docker to run Python?<\/h2>\n<p><!-- before seo:\n\n\n<h2>Why do we need Docker?<\/h2>\n\n\n--><br \/>\nRunning Python on Docker has many advantages, here are a few:<\/p>\n<ul>\n<li>Faster development process<\/li>\n<li>Handy application encapsulation<\/li>\n<li>The same behaviour on local machine \/ dev \/ staging \/ production servers<\/li>\n<li>Easy and clear monitoring<\/li>\n<li>Easy to scale<\/li>\n<\/ul>\n<h3>Faster development process<\/h3>\n<p>There is no need to install 3rd-party apps like PostgreSQL, Redis, Elasticsearch on the system \u2013 you can run it in containers. Docker in Python also gives you the ability to run different versions of the same application simultaneously. For example, say you need to do some manual data migration from an older version of Postgres to a newer version. You can have such a situation in microservice architecture when you want to create a new microservice with a new version of the 3rd-party software.<\/p>\n<p>It could be quite complex to keep two different versions of the same app on one host OS. In this case, Python Docker containers could be a perfect solution <!--In this case, Docker containers could be a perfect solution-->\u2013 you receive isolated environments for your applications and 3rd-parties.<br \/>\nAlso, depending on your stack, you can manage several programming language versions in containers of Docker: Python 3.9 and Python 3.7 for example.<\/p>\n<h3>Handy application encapsulation<\/h3>\n<p>You can deliver your application in one piece. Most programming languages, frameworks and all operating systems have their own packaging managers. And even if your application can be packed with its native package manager, it could be hard to create a port for another system.<\/p>\n<p>Supporting various languages, including Python, Docker gives you a unified image format to distribute your applications across different host systems and cloud services. You can deliver your application in one piece with all the required dependencies (included in an image) ready to run.<\/p>\n<p>Thus, helping development teams with delivering and deploying packaged applications in Python, containers can increase the convenience and speed of the development process.<\/p>\n<h3>Same behaviour on local machine \/ dev \/ staging \/ production servers<\/h3>\n<p>Docker can\u2019t guarantee 100% dev \/ staging \/ production parity, because there is always the human factor. But it reduces to almost zero the probability of error caused by different versions of operating systems, system-dependencies, etc.<\/p>\n<p>With the right approach to building Docker images, your application will use the same base image with the same OS version and the required dependencies.<\/p>\n<h3>Easy and clear monitoring<\/h3>\n<p>Out of the box, you have a unified way to read log files from all running Docker container with Python.<!-- Out of the box, you have a unified way to read log files from all running containers.--> You don&#8217;t need to remember all the specific paths where your app and its dependencies store log files and write custom hooks to handle this.<\/p>\n<p>You can integrate an <a href=\"https:\/\/docs.docker.com\/config\/containers\/logging\/configure\/#supported-logging-drivers\">external logging driver<\/a> and monitor your app log files in one place.<\/p>\n<h3>Easy to scale<\/h3>\n<p>A correctly wrapped application will cover most of the <a href=\"https:\/\/12factor.net\/\">Twelve Factors<\/a>. By design, Docker forces you follow its core principles, such as configuration over environment variables, communication over TCP\/UDP ports, etc. And if you\u2019ve done your application right, it will be ready for scaling not only in Docker.<\/p>\n<h2>Supported platforms<\/h2>\n<p>Docker\u2019s native platform is Linux, as it\u2019s based on features provided by the Linux kernel. It allows, for example, easy adding Docker on Ubuntu for Python projects of yours. However, you can still run it on macOS and Windows. The only difference is that on macOS and Windows, Docker is encapsulated into a tiny virtual machine. At the moment, Docker for macOS and Windows has reached a significant level of usability and feels more like a native app.<\/p>\n<p>That support brings more flexibility to using the Docker+Python combo for development, considering that your choice of a particular platform may depend not only on personal preferences but also on many other reasons.<\/p>\n<h2>Installation<\/h2>\n<p>You can check out the installation instructions for Docker <a href=\"https:\/\/docs.docker.com\/install\/\">here<\/a>.<\/p>\n<p>If you&#8217;re running Docker on Linux, you need to run all the following commands as root or add your user to docker group and re-login:<\/p>\n<pre><code class=\"language- language bash\">sudo usermod -aG docker $(whoami)`\r\n<\/code><\/pre>\n<h2>Terminology<\/h2>\n<ul>\n<li><strong>Container<\/strong> \u2013 a running instance that encapsulates required software. Containers are always created from images. A container can expose ports and volumes to interact with other containers or\/and the outer world. Containers can be easily killed \/ removed and re-created again in a very short time. Containers don&#8217;t keep state.<\/li>\n<li><strong>Image<\/strong> \u2013 the basic element for every container. When you create an image, every step is cached and can be reused (<a href=\"https:\/\/en.wikipedia.org\/wiki\/Copy-on-write\">Copy On Write model<\/a>). Depending on the image, it can take some time to build. Containers, on the other hand, can be started from images right away.\u00a0When you code in Python, Docker images can reduce the configuration hassle.<\/li>\n<li><strong>Port<\/strong> \u2013 a TCP\/UDP port in its original meaning. To keep things simple, let\u2019s assume that ports can be exposed to the outer world (accessible from the host OS) or connected to other containers \u2013 i.e., accessible only from those containers and invisible to the outer world.<\/li>\n<li><strong>Volume<\/strong> \u2013 can be described as a shared folder. Volumes are initialized when a container is created. Volumes are designed to persist data, independent of the container\u2019s lifecycle.<\/li>\n<li><strong>Registry<\/strong> \u2013 the server that stores Docker images. It can be compared to Github \u2013 you can pull an image from the registry to deploy it locally, and push locally built images to the registry.<\/li>\n<li><a href=\"https:\/\/hub.docker.com\/search?q=&amp;type=image\"><strong>Docker Hub<\/strong><\/a> \u2013 a registry with web interface provided by Docker Inc. It stores a lot of Docker images with different software. Docker Hub is a source of the &#8220;official&#8221; Docker images made by the Docker team or in cooperation with the original software manufacturer (it doesn&#8217;t necessarily mean that these &#8220;original&#8221; images are from official software manufacturers). Official images list their potential vulnerabilities. This information is available to any logged-in user. There are both free and paid accounts available. You can have one private image per account and an infinite amount of public images for free. <a href=\"https:\/\/hub.docker.com\/search?q=&amp;source=verified&amp;type=image\" target=\"_blank\" rel=\"nofollow noopener\"><strong>Docker Store<\/strong><\/a> \u2013 a service very similar to Docker Hub. It&#8217;s a marketplace with ratings, reviews, etc. My personal opinion is that it&#8217;s marketing stuff. I&#8217;m totally happy with Docker Hub.<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/djangostars.com\/blog\/content\/images\/2017\/03\/docker-vulnera.png\" alt=\"3rd party vulnerabilities Docker hub\" \/><\/p>\n<h2>Example 1: hello world<\/h2>\n<p>It\u2019s time to run Python in Docker with your first container:<!--It's time to run your first container:--><\/p>\n<pre><code class=\"language- language bash\">docker run ubuntu \/bin\/echo 'Hello world'\r\n<\/code><\/pre>\n<p>Console output:<\/p>\n<pre><code class=\"language- language bash\">Unable to find image 'ubuntu:latest' locally\r\nlatest: Pulling from library\/ubuntu\r\n6b98dfc16071: Pull complete\r\n4001a1209541: Pull complete\r\n6319fc68c576: Pull complete\r\nb24603670dc3: Pull complete\r\n97f170c87c6f: Pull complete\r\nDigest:sha256:5f4bdc3467537cbbe563e80db2c3ec95d548a9145d64453b06939c4592d67b6d\r\nStatus: Downloaded newer image for ubuntu:latest\r\nHello world\r\n<\/code><\/pre>\n<ul>\n<li><strong>docker run<\/strong> is a command to run a container.<\/li>\n<li><strong>ubuntu<\/strong> is the image you run. For example, the Ubuntu operating system image. When you specify an image, Docker looks first for the image on your Docker host. If the image does not exist locally, then the image is pulled from the public image registry \u2013 Docker Hub.<\/li>\n<li><strong>\/bin\/echo &#8216;Hello world&#8217;<\/strong> is the command that will run inside a new container. This container simply prints \u201cHello world\u201d and stops the execution.<\/li>\n<\/ul>\n<p>Let\u2019s try to create an interactive shell inside a Docker container:<\/p>\n<pre><code class=\"language- language bash\">docker run -i -t --rm ubuntu \/bin\/bash\r\n<\/code><\/pre>\n<ul>\n<li><strong>-t<\/strong> flag assigns a pseudo-tty or terminal inside the new container.<\/li>\n<li><strong>-i<\/strong> flag allows you to make an interactive connection by grabbing the standard input (STDIN) of the container.<\/li>\n<li><strong>&#8211;rm<\/strong> flag automatically removes the container when the process exits. By default, containers are not deleted. This container exists until we keep the shell session and terminates when we exit the session (like an SSH session with a remote server).<\/li>\n<\/ul>\n<p>If you want to keep the container running after the end of the session, you need to daemonize it:<\/p>\n<pre><code class=\"language- language bash\">docker run --name daemon -d ubuntu \/bin\/sh -c \"while true; do echo hello world; sleep 1; done\"\r\n<\/code><\/pre>\n<ul>\n<li><strong>&#8211;name daemon<\/strong> assigns daemon name to a new container. If you don\u2019t specify a name explicitly, Docker will generate and assign it automatically.<\/li>\n<li><strong>-d<\/strong> flag runs the container in the background (i.e., daemonizes it).<\/li>\n<\/ul>\n<p>Let\u2019s see what containers we have at the moment:<\/p>\n<pre><code class=\"language- language bash\">docker ps -a\r\n<\/code><\/pre>\n<p>Console output:<\/p>\n<pre><code class=\"language- language bash\">CONTAINER ID  IMAGE   COMMAND                 CREATED             STATUS                         PORTS  NAMES\r\n1fc8cee64ec2  ubuntu  \"\/bin\/sh -c 'while...\"  32 seconds ago      Up 30 seconds                         daemon\r\nc006f1a02edf  ubuntu  \"\/bin\/echo 'Hello ...\"  About a minute ago  Exited (0) About a minute ago         gifted_nobel\r\n<\/code><\/pre>\n<ul>\n<li><strong>docker ps<\/strong> is a command to list containers.<\/li>\n<li><strong>-a<\/strong> shows all containers (without -a flag ps will show only running containers).<\/li>\n<\/ul>\n<p>The ps shows us that we have two containers:<\/p>\n<ul>\n<li><strong>gifted_nobel<\/strong> (the name for this container was generated automatically \u2013 it will be different on your machine). It&#8217;s the first container we created, the one that printed &#8216;Hello world&#8217; once.<\/li>\n<li><strong>daemon<\/strong> \u2013 the third container we created, which runs as a daemon.<\/li>\n<\/ul>\n<p><strong>Note:<\/strong> there is no second container (the one with interactive shell) because we set the <strong>&#8211;rm option<\/strong>. As a result, this container is automatically deleted right after execution.<br \/>\nLet\u2019s check the logs and see what the daemon container is doing right now:<\/p>\n<pre><code class=\"language-language bash\">docker logs -f daemon\r\n<\/code><\/pre>\n<p>Console output:<\/p>\n<pre><code class=\"language-language bash\">...\r\nhello world\r\nhello world\r\nhello world\r\n<\/code><\/pre>\n<ul>\n<li><strong>docker logs<\/strong> fetch the logs of a container.<\/li>\n<li><strong>-f<\/strong> flag to follow the log output (works actually like <strong>tail -f<\/strong>).<\/li>\n<\/ul>\n<p>Now let\u2019s stop the daemon container:<\/p>\n<pre><code class=\"language-language bash\">docker stop daemon\r\n<\/code><\/pre>\n<p>Make sure the container has stopped.<\/p>\n<pre><code class=\"language-language bash\">docker ps -a\r\n<\/code><\/pre>\n<p>Console output:<\/p>\n<pre><code class=\"language-language bash\">CONTAINER ID  IMAGE   COMMAND                 CREATED        STATUS                      PORTS  NAMES\r\n1fc8cee64ec2  ubuntu  \"\/bin\/sh -c 'while...\"  5 minutes ago  Exited (137) 5 seconds ago         daemon\r\nc006f1a02edf  ubuntu  \"\/bin\/echo 'Hello ...\"  6 minutes ago  Exited (0) 6 minutes ago           gifted_nobel\r\n<\/code><\/pre>\n<p>The container is stopped. We can start it again:<\/p>\n<pre><code class=\"language-language bash\">docker start daemon\r\n<\/code><\/pre>\n<p>Let\u2019s ensure that it\u2019s running:<\/p>\n<pre><code class=\"language-language bash\">docker ps -a\r\n<\/code><\/pre>\n<p>Console output:<\/p>\n<pre><code class=\"language-language bash\">CONTAINER ID  IMAGE   COMMAND                 CREATED        STATUS                    PORTS  NAMES\r\n1fc8cee64ec2  ubuntu  \"\/bin\/sh -c 'while...\"  5 minutes ago  Up 3 seconds                     daemon\r\nc006f1a02edf  ubuntu  \"\/bin\/echo 'Hello ...\"  6 minutes ago  Exited (0) 7 minutes ago         gifted_nobel\r\n<\/code><\/pre>\n<p>Now, stop it again and remove all the containers manually:<\/p>\n<pre><code class=\"language- language bash\">docker stop daemon\r\ndocker rm &lt;your first container name&gt;\r\ndocker rm daemon\r\n<\/code><\/pre>\n<p>To remove all containers, we can use the following command:<\/p>\n<pre><code class=\"language- language bash\">docker rm -f $(docker ps -aq)\r\n<\/code><\/pre>\n<ul>\n<li><strong>docker rm<\/strong> is the command to remove the container.<\/li>\n<li><strong>-f<\/strong> flag (for rm) stops the container if it&#8217;s running (i.e., force deletion).<\/li>\n<li><strong>-q<\/strong> flag (for ps) is to print only container IDs.<\/li>\n<\/ul>\n<h2>Example 2: Environment variables and volumes<\/h2>\n<p>Starting from this example, you&#8217;ll need several additional files you can find on my <a href=\"https:\/\/github.com\/alexryabtsev\/docker-workshop\/\">GitHub repo<\/a>. You can clone my repo or simply use the <a href=\"https:\/\/github.com\/alexryabtsev\/docker-workshop\/archive\/master.zip\">following link<\/a> to download the sample files.<\/p>\n<p>It\u2019s time to create and run more a meaningful container, like <strong>Nginx<\/strong>.<\/p>\n<p>Change the directory to <strong>examples\/nginx<\/strong>:<\/p>\n<pre><code class=\"language- language bash\">docker run -d --name \"test-nginx\" -p 8080:80 -v $(pwd):\/usr\/share\/nginx\/html:ro nginx:latest\r\n<\/code><\/pre>\n<p><strong>Warning<\/strong>: This command looks quite heavy, but it&#8217;s just an example to explain volumes and env variables. In 99% of real-life cases, you won&#8217;t start Docker containers manually \u2013 you&#8217;ll use orchestration services (we&#8217;ll cover <a href=\"https:\/\/docs.docker.com\/compose\/overview\/\">docker-compose<\/a> in <a href=\"https:\/\/github.com\/alexryabtsev\/docker-workshop#example-4-connection-between-containers\">example #4<\/a>) or write a custom script to do it.<\/p>\n<p>Console output:<\/p>\n<pre><code class=\"language- language bash\">Unable to find image 'nginx:latest' locally\r\nlatest: Pulling from library\/nginx\r\n683abbb4ea60: Pull complete\r\na470862432e2: Pull complete\r\n977375e58a31: Pull complete\r\nDigest: sha256:a65beb8c90a08b22a9ff6a219c2f363e16c477b6d610da28fe9cba37c2c3a2ac\r\nStatus: Downloaded newer image for nginx:latest\r\nafa095a8b81960241ee92ecb9aa689f78d201cff2469895674cec2c2acdcc61c\r\n<\/code><\/pre>\n<ul>\n<li><strong>-p<\/strong> is a ports mapping HOST PORT:CONTAINER PORT.<\/li>\n<li><strong>-v<\/strong> is a volume mounting HOST DIRECTORY:CONTAINER DIRECTORY.<\/li>\n<\/ul>\n<p><strong>Important<\/strong>: run command accepts only absolute paths. In our example, we&#8217;ve used <strong>$(pwd)<\/strong> to set the current directory absolute path.<\/p>\n<p>Now check this url &#8211; 127.0.0.1:8080 in your web browser.<\/p>\n<p>We can try to change <strong>\/example\/nginx\/index.html<\/strong> (which is mounted as a volume to <strong>\/usr\/share\/nginx\/html<\/strong> directory inside the container) and refresh the page.<br \/>\nLet\u2019s get the information about the <strong>test-nginx<\/strong> container:<\/p>\n<pre><code class=\"language- language bash\">docker inspect test-nginx\r\n<\/code><\/pre>\n<p>This command displays system-wide information about the Docker installation. This information includes the kernel version, number of containers and images, exposed ports, mounted volumes, etc.<\/p>\n<h2>Example 3: Writing your first Dockerfile<\/h2>\n<p>To build a Docker image, you need to create a Dockerfile. It is a plain text file with instructions and arguments. Here is the description of the instructions we\u2019re going to use in our next example:<\/p>\n<ul>\n<li><strong>FROM<\/strong> &#8212; set base image<\/li>\n<li><strong>RUN<\/strong> &#8212; execute command in container<\/li>\n<li><strong>ENV<\/strong> &#8212; set environment variable<\/li>\n<li><strong>WORKDIR<\/strong> &#8212; set working directory<\/li>\n<li><strong>VOLUME<\/strong> &#8212; create mount-point for a volume<\/li>\n<li><strong>CMD<\/strong> &#8212; set executable for container<\/li>\n<\/ul>\n<p>You can check <a href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/\">Dockerfile reference<\/a> for more details.<\/p>\n<p>Let\u2019s create an image that will get the contents of the website with <strong>curl<\/strong> and store it to the text file. We need to pass the website url via the environment variable <strong>SITE_URL<\/strong>. The resulting file will be placed in a directory, mounted as a volume.<\/p>\n<p>Place the file name <strong>Dockerfile<\/strong> in <strong>examples\/curl<\/strong> directory with the following contents:<\/p>\n<pre><code class=\"language- language bash\">FROM ubuntu:latest\r\nRUN apt-get update\r\n    &amp;&amp; apt-get install --no-install-recommends --no-install-suggests -y curl\r\n    &amp;&amp; rm -rf \/var\/lib\/apt\/lists\/*\r\nENV SITE_URL http:\/\/example.com\/\r\nWORKDIR \/data\r\nVOLUME \/data\r\nCMD sh -c \"curl -Lk $SITE_URL &gt; \/data\/results\"\r\n<\/code><\/pre>\n<p>Dockerfile is ready. It\u2019s time to build the actual image.<br \/>\nGo to <strong>examples\/curl<\/strong> directory and execute the following command to build an image:<\/p>\n<pre><code class=\"language- language bash\">docker build . -t test-curl\r\n<\/code><\/pre>\n<p>Console output:<\/p>\n<pre><code class=\"language- language bash\">Sending build context to Docker daemon  3.584kB\r\nStep 1\/6 : FROM ubuntu:latest\r\n ---&gt; 113a43faa138\r\nStep 2\/6 : RUN apt-get update     &amp;&amp; apt-get install --no-install-recommends --no-install-suggests -y curl     &amp;&amp; rm -rf \/var\/lib\/apt\/lists\/*\r\n ---&gt; Running in ccc047efe3c7\r\nGet:1 http:\/\/archive.ubuntu.com\/ubuntu bionic InRelease [242 kB]\r\nGet:2 http:\/\/security.ubuntu.com\/ubuntu bionic-security InRelease [83.2 kB]\r\n...\r\nRemoving intermediate container ccc047efe3c7\r\n ---&gt; 8d10d8dd4e2d\r\nStep 3\/6 : ENV SITE_URL http:\/\/example.com\/\r\n ---&gt; Running in 7688364ef33f\r\nRemoving intermediate container 7688364ef33f\r\n ---&gt; c71f04bdf39d\r\nStep 4\/6 : WORKDIR \/data\r\nRemoving intermediate container 96b1b6817779\r\n ---&gt; 1ee38cca19a5\r\nStep 5\/6 : VOLUME \/data\r\n ---&gt; Running in ce2c3f68dbbb\r\nRemoving intermediate container ce2c3f68dbbb\r\n ---&gt; f499e78756be\r\nStep 6\/6 : CMD sh -c \"curl -Lk $SITE_URL &gt; \/data\/results\"\r\n ---&gt; Running in 834589c1ac03\r\nRemoving intermediate container 834589c1ac03\r\n ---&gt; 4b79e12b5c1d\r\nSuccessfully built 4b79e12b5c1d\r\nSuccessfully tagged test-curl:latest\r\n<\/code><\/pre>\n<ul>\n<li><strong>docker build<\/strong> command builds a new image locally.<\/li>\n<li><strong>-t<\/strong> flag sets the name tag to an image.<\/li>\n<\/ul>\n<p>Now we have the new image, and we can see it in the list of existing images:<\/p>\n<pre><code class=\"language- language bash\">docker images\r\n<\/code><\/pre>\n<p>Console output:<\/p>\n<pre><code class=\"language- language bash\">REPOSITORY  TAG     IMAGE ID      CREATED         SIZE\r\ntest-curl   latest  5ebb2a65d771  37 minutes ago  180 MB\r\nnginx       latest  6b914bbcb89e  7 days ago      182 MB\r\nubuntu      latest  0ef2e08ed3fa  8 days ago      130 MB\r\n<\/code><\/pre>\n<p>We can create and run the container from the image. Let\u2019s try it with the default parameters:<\/p>\n<pre><code class=\"language- language bash\">docker run --rm -v $(pwd)\/vol:\/data\/:rw test-curl\r\n<\/code><\/pre>\n<p>To see the results saved to file, run:<\/p>\n<pre><code class=\"language- language bash\">cat .\/vol\/results\r\n<\/code><\/pre>\n<p>Let\u2019s try with Facebook.com:<\/p>\n<pre><code class=\"language- language bash\">docker run --rm -e SITE_URL=https:\/\/facebook.com\/ -v $(pwd)\/vol:\/data\/:rw test-curl\r\n<\/code><\/pre>\n<p>To see the results saved to file, run:<\/p>\n<pre><code class=\"language- language bash\">cat .\/vol\/results\r\n<\/code><\/pre>\n<div class=\"info_box_shortcode_holder\" style=\"background-image: url(https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2023\/08\/Web-Development_2.png)\">\n    <div class=\"info_box_label\">\n    Services\n    <\/div>\n    <div class=\"info_box_logo\">\n    \n    <\/div>\n    \n    <div class=\"info_box_title font_size_\">\n   <span class=\"info_box_title_inner\">Explore our Software Architrcture Services.&lt;br \/&gt;\n<\/span>\n    <\/div>\n    <div class=\"info_box_link\">\n        <a href=\"https:\/\/djangostars.com\/services\/digital-product-development\/#software_architecture\" target=\"_blank\" >\n            <span>Learn More<\/span>\n            <div class=\"button_animated\">\n                <svg width=\"24\" height=\"12\" viewBox=\"0 0 24 12\" fill=\"none\"\n                     xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                    <path d=\"M23.725 5.33638C23.7248 5.3361 23.7245 5.33577 23.7242 5.33549L18.8256 0.460497C18.4586 0.0952939 17.865 0.096653 17.4997 0.463684C17.1345 0.830668 17.1359 1.42425 17.5028 1.7895L20.7918 5.06249H0.9375C0.419719 5.06249 0 5.48221 0 5.99999C0 6.51777 0.419719 6.93749 0.9375 6.93749H20.7917L17.5029 10.2105C17.1359 10.5757 17.1345 11.1693 17.4998 11.5363C17.865 11.9034 18.4587 11.9046 18.8256 11.5395L23.7242 6.66449C23.7245 6.66421 23.7248 6.66388 23.7251 6.6636C24.0923 6.29713 24.0911 5.70163 23.725 5.33638Z\"\n                          fill=\"#282828\"><\/path>\n                <\/svg>\n                <div class=\"shape\"><\/div>\n            <\/div>\n        <\/a>\n    <\/div>\n<\/div>\n<h2>Best practices for creating Docker images<\/h2>\n<ul>\n<li>Include only <strong>necessary context<\/strong> \u2013 use a <a href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#dockerignore-file\"><strong>.dockerignore<\/strong><\/a> file (like .gitignore in git)<\/li>\n<li>Avoid installing <strong>unnecessary packages<\/strong> \u2013 it will consume extra disk space.<\/li>\n<li><strong>Use cache<\/strong>. Add context that changes a lot (for example, the source code of your project) at the end of Dockerfile \u2013 it will utilize Docker cache effectively.<\/li>\n<li><strong>Be careful with volumes<\/strong>. You should remember what data is in volumes. Because volumes are persistent and don\u2019t die with the containers, the next container will use data from the volume created by the previous container.<\/li>\n<li>Use <a href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#environment-replacement\"><strong>environment variables<\/strong><\/a> (in RUN, EXPOSE, VOLUME). It will make your Dockerfile more flexible.<\/li>\n<\/ul>\n<h2>Alpine images<\/h2>\n<p>A lot of Docker images (versions of images) are created on top of <a href=\"https:\/\/alpinelinux.org\/\"><strong>Alpine Linux<\/strong><\/a> \u2013 this is a lightweight distro that allows you to reduce the overall size of Docker images.<\/p>\n<p>I recommend that you use images based on Alpine for third-party services, such as Redis, Postgres, etc. For your app images, use images based on <a href=\"https:\/\/hub.docker.com\/_\/buildpack-deps\/\"><strong>buildpack<\/strong><\/a> \u2013 it will be easy to debug inside the container, and you&#8217;ll have a lot of pre-installed system-wide requirements.<\/p>\n<p>Only you can decide which base image to use, but you can get the maximum benefit by using one basic image for all images, because in this case the cache will be used more effectively.<\/p>\n<h2>Example 4: Connection between containers<\/h2>\n<p><a href=\"https:\/\/docs.docker.com\/compose\/overview\/\"><strong>Docker compose<\/strong><\/a> &#8212; is an CLI utility used to connect containers with each other.<br \/>\nYou can install docker-compose <a href=\"https:\/\/pypi.org\/project\/docker-compose\/\">via pip<\/a>:<\/p>\n<pre><code class=\"language- language bash\">sudo pip install docker-compose\r\n<\/code><\/pre>\n<p>In this example, I am going to connect Python and Redis containers.<\/p>\n<pre><code class=\"language- language bash\">version: '3.6'\r\nservices:\r\n  app:\r\n    build:\r\n      context: .\/app\r\n    depends_on:\r\n      - redis\r\n    environment:\r\n      - REDIS_HOST=redis\r\n    ports:\r\n      - \"5000:5000\"\r\n  redis:\r\n    image: redis:3.2-alpine\r\n    volumes:\r\n      - redis_data:\/data\r\nvolumes:\r\n  redis_data:\r\n<\/code><\/pre>\n<p>Go to <strong>examples\/compose<\/strong> and execute the following command:<\/p>\n<pre><code class=\"language- language bash\">docker-compose up\r\n<\/code><\/pre>\n<p>Console output:<\/p>\n<pre><code class=\"language- language bash\">Building app\r\nStep 1\/9 : FROM python:3.6.3\r\n3.6.3: Pulling from library\/python\r\nf49cf87b52c1: Pull complete\r\n7b491c575b06: Pull complete\r\nb313b08bab3b: Pull complete\r\n51d6678c3f0e: Pull complete\r\n09f35bd58db2: Pull complete\r\n1bda3d37eead: Pull complete\r\n9f47966d4de2: Pull complete\r\n9fd775bfe531: Pull complete\r\nDigest: sha256:cdef88d8625cf50ca705b7abfe99e8eb33b889652a9389b017eb46a6d2f1aaf3\r\nStatus: Downloaded newer image for python:3.6.3\r\n ---&gt; a8f7167de312\r\nStep 2\/9 : ENV BIND_PORT 5000\r\n ---&gt; Running in 3b6fe5ca226d\r\nRemoving intermediate container 3b6fe5ca226d\r\n ---&gt; 0b84340fa920\r\nStep 3\/9 : ENV REDIS_HOST localhost\r\n ---&gt; Running in a4f9a1d6f541\r\nRemoving intermediate container a4f9a1d6f541\r\n ---&gt; ebe63bf5959e\r\nStep 4\/9 : ENV REDIS_PORT 6379\r\n ---&gt; Running in fd06aa65fd33\r\nRemoving intermediate container fd06aa65fd33\r\n ---&gt; 2a581c31ff4f\r\nStep 5\/9 : COPY .\/requirements.txt \/requirements.txt\r\n ---&gt; 671093a12829\r\nStep 6\/9 : RUN pip install -r \/requirements.txt\r\n ---&gt; Running in b8ea53bc6ba6\r\nCollecting flask==1.0.2 (from -r \/requirements.txt (line 1))\r\n  Downloading https:\/\/files.pythonhosted.org\/packages\/7f\/e7\/08578774ed4536d3242b14dacb4696386634607af824ea997202cd0edb4b\/Flask-1.0.2-py2.py3-none-any.whl (91kB)\r\nCollecting redis==2.10.6 (from -r \/requirements.txt (line 2))\r\n  Downloading https:\/\/files.pythonhosted.org\/packages\/3b\/f6\/7a76333cf0b9251ecf49efff635015171843d9b977e4ffcf59f9c4428052\/redis-2.10.6-py2.py3-none-any.whl (64kB)\r\nCollecting click&gt;=5.1 (from flask==1.0.2-&gt;-r \/requirements.txt (line 1))\r\n  Downloading https:\/\/files.pythonhosted.org\/packages\/34\/c1\/8806f99713ddb993c5366c362b2f908f18269f8d792aff1abfd700775a77\/click-6.7-py2.py3-none-any.whl (71kB)\r\nCollecting Jinja2&gt;=2.10 (from flask==1.0.2-&gt;-r \/requirements.txt (line 1))\r\n  Downloading https:\/\/files.pythonhosted.org\/packages\/7f\/ff\/ae64bacdfc95f27a016a7bed8e8686763ba4d277a78ca76f32659220a731\/Jinja2-2.10-py2.py3-none-any.whl (126kB)\r\nCollecting itsdangerous&gt;=0.24 (from flask==1.0.2-&gt;-r \/requirements.txt (line 1))\r\n  Downloading https:\/\/files.pythonhosted.org\/packages\/dc\/b4\/a60bcdba945c00f6d608d8975131ab3f25b22f2bcfe1dab221165194b2d4\/itsdangerous-0.24.tar.gz (46kB)\r\nCollecting Werkzeug&gt;=0.14 (from flask==1.0.2-&gt;-r \/requirements.txt (line 1))\r\n  Downloading https:\/\/files.pythonhosted.org\/packages\/20\/c4\/12e3e56473e52375aa29c4764e70d1b8f3efa6682bef8d0aae04fe335243\/Werkzeug-0.14.1-py2.py3-none-any.whl (322kB)\r\nCollecting MarkupSafe&gt;=0.23 (from Jinja2&gt;=2.10-&gt;flask==1.0.2-&gt;-r \/requirements.txt (line 1))\r\n  Downloading https:\/\/files.pythonhosted.org\/packages\/4d\/de\/32d741db316d8fdb7680822dd37001ef7a448255de9699ab4bfcbdf4172b\/MarkupSafe-1.0.tar.gz\r\nBuilding wheels for collected packages: itsdangerous, MarkupSafe\r\n  Running setup.py bdist_wheel for itsdangerous: started\r\n  Running setup.py bdist_wheel for itsdangerous: finished with status 'done'\r\n  Stored in directory: \/root\/.cache\/pip\/wheels\/2c\/4a\/61\/5599631c1554768c6290b08c02c72d7317910374ca602ff1e5\r\n  Running setup.py bdist_wheel for MarkupSafe: started\r\n  Running setup.py bdist_wheel for MarkupSafe: finished with status 'done'\r\n  Stored in directory: \/root\/.cache\/pip\/wheels\/33\/56\/20\/ebe49a5c612fffe1c5a632146b16596f9e64676768661e4e46\r\nSuccessfully built itsdangerous MarkupSafe\r\nInstalling collected packages: click, MarkupSafe, Jinja2, itsdangerous, Werkzeug, flask, redis\r\nSuccessfully installed Jinja2-2.10 MarkupSafe-1.0 Werkzeug-0.14.1 click-6.7 flask-1.0.2 itsdangerous-0.24 redis-2.10.6\r\nYou are using pip version 9.0.1, however version 10.0.1 is available.\r\nYou should consider upgrading via the 'pip install --upgrade pip' command.\r\nRemoving intermediate container b8ea53bc6ba6\r\n ---&gt; 3117d3927951\r\nStep 7\/9 : COPY .\/app.py \/app.py\r\n ---&gt; 84a82fa91773\r\nStep 8\/9 : EXPOSE $BIND_PORT\r\n ---&gt; Running in 8e259617b7b5\r\nRemoving intermediate container 8e259617b7b5\r\n ---&gt; 55f447f498dd\r\nStep 9\/9 : CMD [ \"python\", \"\/app.py\" ]\r\n ---&gt; Running in 2ade293ecb25\r\nRemoving intermediate container 2ade293ecb25\r\n ---&gt; b85b4246e9f8\r\nSuccessfully built b85b4246e9f8\r\nSuccessfully tagged compose_app:latest\r\nWARNING: Image for service app was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.\r\nCreating compose_redis_1 ... done\r\nCreating compose_app_1   ... done\r\nAttaching to compose_redis_1, compose_app_1\r\nredis_1  | 1:C 08 Jul 18:12:21.851 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server \/path\/to\/redis.conf\r\nredis_1  |                 _._\r\nredis_1  |            _.-``__ ''-._\r\nredis_1  |       _.-``    `.  `_.  ''-._           Redis 3.2.12 (00000000\/0) 64 bit\r\nredis_1  |   .-`` .-```.  ```\/    _.,_ ''-._\r\nredis_1  |  (    '      ,       .-`  | `,    )     Running in standalone mode\r\nredis_1  |  |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379\r\nredis_1  |  |    `-._   `._    \/     _.-'    |     PID: 1\r\nredis_1  |   `-._    `-._  `-.\/  _.-'    _.-'\r\nredis_1  |  |`-._`-._    `-.__.-'    _.-'_.-'|\r\nredis_1  |  |    `-._`-._        _.-'_.-'    |           http:\/\/redis.io\r\nredis_1  |   `-._    `-._`-.__.-'_.-'    _.-'\r\nredis_1  |  |`-._`-._    `-.__.-'    _.-'_.-'|\r\nredis_1  |  |    `-._`-._        _.-'_.-'    |\r\nredis_1  |   `-._    `-._`-.__.-'_.-'    _.-'\r\nredis_1  |       `-._    `-.__.-'    _.-'\r\nredis_1  |           `-._        _.-'\r\nredis_1  |               `-.__.-'\r\nredis_1  |\r\nredis_1  | 1:M 08 Jul 18:12:21.852 # WARNING: The TCP backlog setting of 511 cannot be enforced because \/proc\/sys\/net\/core\/somaxconn is set to the lower value of 128.\r\nredis_1  | 1:M 08 Jul 18:12:21.852 # Server started, Redis version 3.2.12\r\nredis_1  | 1:M 08 Jul 18:12:21.852 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to \/etc\/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.\r\nredis_1  | 1:M 08 Jul 18:12:21.852 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never &gt; \/sys\/kernel\/mm\/transparent_hugepage\/enabled' as root, and add it to your \/etc\/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.\r\nredis_1  | 1:M 08 Jul 18:12:21.852 * The server is now ready to accept connections on port 6379\r\napp_1    |  * Serving Flask app \"app\" (lazy loading)\r\napp_1    |  * Environment: production\r\napp_1    |    WARNING: Do not use the development server in a production environment.\r\napp_1    |    Use a production WSGI server instead.\r\napp_1    |  * Debug mode: on\r\napp_1    |  * Running on http:\/\/0.0.0.0:5000\/ (Press CTRL+C to quit)\r\napp_1    |  * Restarting with stat\r\napp_1    |  * Debugger is active!\r\napp_1    |  * Debugger PIN: 170-528-240\r\n<\/code><\/pre>\n<p>The current example of connecting Python to Docker containers will increment view counter in Redis. Open adress 127.0.0.1:5000 in your web browser and check it.<\/p>\n<p>How to use docker-compose is a topic for a separate tutorial. To get started, you can play with some images from Docker Hub. If you want to create your own images, follow the best practices listed above. The only thing I can add in terms of using docker-compose is that you should <strong>always give explicit names to your volumes<\/strong> in docker-compose.yml (if the image has volumes). This simple rule will save you from an issue in the future when you&#8217;ll be inspecting your volumes.<\/p>\n<pre><code class=\"language- language bash\">version: '3.6'\r\nservices:\r\n  ...\r\n  redis:\r\n    image: redis:3.2-alpine\r\n    volumes:\r\n      - redis_data:\/data\r\nvolumes:\r\n  redis_data:\r\n<\/code><\/pre>\n<p>In this case, <strong>redis_data<\/strong> will be the name inside the docker-compose.yml file; for the real volume name, it will be prepended with project name prefix.<br \/>\nTo see volumes, run:<\/p>\n<pre><code class=\"language- language bash\">docker volume ls\r\n<\/code><\/pre>\n<p>Console output:<\/p>\n<pre><code class=\"language- language bash\">DRIVER              VOLUME NAME\r\nlocal               apptest_redis_data\r\n<\/code><\/pre>\n<p>Without an explicit volume name, there will be a UUID. Here\u2019s an example from my local machine:<\/p>\n<pre><code class=\"language- language bash\">DRIVER              VOLUME NAME\r\nlocal               ec1a5ac0a2106963c2129151b27cb032ea5bb7c4bd6fe94d9dd22d3e72b2a41b\r\nlocal               f3a664ce353ba24dd43d8f104871594de6024ed847054422bbdd362c5033fc4c\r\nlocal               f81a397776458e62022610f38a1bfe50dd388628e2badc3d3a2553bb08a5467f\r\nlocal               f84228acbf9c5c06da7be2197db37f2e3da34b7e8277942b10900f77f78c9e64\r\nlocal               f9958475a011982b4dc8d8d8209899474ea4ec2c27f68d1a430c94bcc1eb0227\r\nlocal               ff14e0e20d70aa57e62db0b813db08577703ff1405b2a90ec88f48eb4cdc7c19\r\nlocal               polls_pg_data\r\nlocal               polls_public_files\r\nlocal               polls_redis_data\r\nlocal               projectdev_pg_data\r\nlocal               projectdev_redis_data\r\n<\/code><\/pre>\n<h2>Docker way<\/h2>\n<p>Docker has some restrictions and requirements, depending on the architecture of your system (applications that you pack into containers). You can ignore these requirements or find some workarounds, but in this case, you won&#8217;t get all the benefits of using Docker. My strong advice is to follow these recommendations:<\/p>\n<ul>\n<li><strong>1 application = 1 container<\/strong>.<\/li>\n<li>Run the process in the <strong>foreground<\/strong> (don&#8217;t use systemd, upstart or any other similar tools).<\/li>\n<li><strong>Keep data out of containers<\/strong> \u2013 use volumes.<\/li>\n<li><strong>Do not use SSH<\/strong> (if you need to step into container, you can use the docker exec command).<\/li>\n<li><strong>Avoid manual configurations<\/strong> (or actions) inside container.<\/li>\n<\/ul>\n<h2>Conclusion<\/h2>\n<p>To summarize this tutorial, alongside with IDE and Git, Docker has become a must-have developer tool that is not only used for delivering <a href=\"https:\/\/djangostars.com\/services\/python-development\/\">custom Python development services<\/a>. It&#8217;s a production-ready tool with a rich and mature infrastructure.<\/p>\n<p>Docker can be used on all types of projects, regardless of size and complexity. In the beginning, you can start with <a href=\"https:\/\/docs.docker.com\/compose\/overview\/\">compose<\/a> and <a href=\"https:\/\/docs.docker.com\/engine\/swarm\/\">Swarm<\/a>. When the project grows, you can migrate to cloud services like <a href=\"https:\/\/aws.amazon.com\/containers\/\">Amazon Container Services<\/a> or <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a>.<\/p>\n<p>Like standard containers used in cargo transportation, wrapping your code in Docker containers will help you build faster and more efficient CI\/CD processes. This is not just another technological trend promoted by a bunch of geeks \u2013 it&#8217;s a new paradigm that is already being used in the architecture of large companies like <a href=\"https:\/\/blog.docker.com\/2017\/12\/containers-at-paypal\/\">PayPal<\/a>, <a href=\"https:\/\/blog.docker.com\/2017\/04\/visa-inc-gains-speed-operational-efficiency-docker-enterprise-edition\/\">Visa<\/a>, <a href=\"https:\/\/www.docker.com\/customers\/\">Swisscom<\/a>, <a href=\"https:\/\/www.docker.com\/customers\/\">General Electric<\/a>, Splunk, etc.<\/p>\n<p><b>To find out which technologies are best to use for <a href=\"https:\/\/djangostars.com\/blog\/top-seven-apps-built-python\/\">apps built with Python<\/a>, <a href=\"https:\/\/djangostars.com\/get-in-touch\/\">discuss it<\/a> with Django Stars specialists<\/b>.<div class=\"lead-form-wrapper lets_disqus\">\n    <div class=\"lead-form transparent-footer\">\n        <p class=\"discuss-title paragraph-discuss col-md-12\">Have an idea? Let&#039;s discuss!<\/p>\n\n        \n<div class=\"wpcf7 no-js\" id=\"wpcf7-f2589-o1\" lang=\"en-US\" dir=\"ltr\" data-wpcf7-id=\"2589\">\n<div class=\"screen-reader-response\"><p role=\"status\" aria-live=\"polite\" aria-atomic=\"true\"><\/p> <ul><\/ul><\/div>\n<form action=\"\/blog\/wp-json\/wp\/v2\/posts\/113#wpcf7-f2589-o1\" method=\"post\" class=\"wpcf7-form init\" aria-label=\"Contact form\" enctype=\"multipart\/form-data\" novalidate=\"novalidate\" data-status=\"init\">\n<div style=\"display: none;\">\n<input type=\"hidden\" name=\"_wpcf7\" value=\"2589\" \/>\n<input type=\"hidden\" name=\"_wpcf7_version\" value=\"6.0.6\" \/>\n<input type=\"hidden\" name=\"_wpcf7_locale\" value=\"en_US\" \/>\n<input type=\"hidden\" name=\"_wpcf7_unit_tag\" value=\"wpcf7-f2589-o1\" \/>\n<input type=\"hidden\" name=\"_wpcf7_container_post\" value=\"0\" \/>\n<input type=\"hidden\" name=\"_wpcf7_posted_data_hash\" value=\"\" \/>\n<input type=\"hidden\" name=\"form_start_time\" value=\"1777566226\" \/>\n<input type=\"hidden\" name=\"_wpcf7_recaptcha_response\" value=\"\" \/>\n<\/div>\n<div class=\"form_holder\">\n    <div class=\"input_section input_row\">\n        <div class=\"input_holder\">\n                            <span class=\"input_label\">\n                               Your name *\n                            <\/span>\n            <input size=\"40\" maxlength=\"400\" class=\"wpcf7-form-control wpcf7-text wpcf7-validates-as-required\" id=\"your-name\" aria-required=\"true\" aria-invalid=\"false\" value=\"\" type=\"text\" name=\"text-898\" \/>\n\n            <input class=\"wpcf7-form-control wpcf7-hidden\" id=\"uniq_ga_id\" value=\"\" type=\"hidden\" name=\"uniq_ga_id\" \/>\n        <\/div>\n        <div class=\"input_holder\">\n                            <span class=\"input_label\">\n                                Your email *\n                            <\/span>\n            <input size=\"40\" maxlength=\"400\" class=\"wpcf7-form-control wpcf7-email wpcf7-validates-as-required wpcf7-text wpcf7-validates-as-email\" id=\"your-email\" aria-required=\"true\" aria-invalid=\"false\" value=\"\" type=\"email\" name=\"email-882\" \/>\n        <\/div>\n    <\/div>\n    <div class=\"input_section single_input_row\">\n        <div class=\"input_holder\">\n            <span class=\"input_label\">How can we help you? *<\/span>\n            <input size=\"40\" maxlength=\"400\" class=\"wpcf7-form-control wpcf7-text\" id=\"message\" aria-invalid=\"false\" value=\"\" type=\"text\" name=\"message\" \/>\n        <\/div>\n    <\/div>\n    <div class=\"file_attach\">\n        <input size=\"40\" class=\"wpcf7-form-control wpcf7-file\" accept=\"audio\/*,video\/*,image\/*\" aria-invalid=\"false\" type=\"file\" name=\"file-930\" \/>\n        <div class=\"file_placeholder\">\ud83d\udcce <span>Attach File<\/span>\n            <span class=\"file_formats\">Formats: pdf, doc, docx, rtf, ppt, pptx.<\/span><\/div>\n    <\/div>\n    <div class=\"checkbox_row\">\n        <div class=\"single_checkbox\"><div class=\"checkbox_indicator\"><div class=\"checked_indicator\"><svg width=\"14\" height=\"12\" viewBox=\"0 0 14 12\" fill=\"none\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M4.66804 12L0 7.26951L1.22426 6.05269L4.54927 9.40456L12.6737 0L14 1.10613L4.66804 12Z\" fill=\"#1E232C\"\/><\/svg><\/div><\/div><input type=\"checkbox\" name=\"agree\" id=\"privacy\" value=\"agree privacy\"><label for=\"privacy\" class=\"\">I have read and accepted <a href=\"https:\/\/djangostars.com\/privacy-policy\/\" style=\"margin-left: 6px;\"> Privacy Policy*<\/a><\/label><\/div>\n        <div class=\"single_checkbox\"><div class=\"checkbox_indicator\"><div class=\"checked_indicator\"><svg width=\"14\" height=\"12\" viewBox=\"0 0 14 12\" fill=\"none\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M4.66804 12L0 7.26951L1.22426 6.05269L4.54927 9.40456L12.6737 0L14 1.10613L4.66804 12Z\" fill=\"#1E232C\"\/><\/svg><\/div><\/div><input type=\"checkbox\" name=\"agree\" id=\"marketing\" value=\"agree for marketing\"><label for=\"marketing\" class=\"\">I agree to receive marketing content from Django Stars<\/label><\/div>\n    <\/div>\n    <div class=\"submit\"><button type=\"submit\"><span>send message<\/span><\/button><div class=\"safeguard\">We safeguard your privacy<\/div><\/div>\n<\/div>\n<div style=\"position: absolute; left: -5000px;\" aria-hidden=\"true\">\n    <input size=\"40\" maxlength=\"400\" class=\"wpcf7-form-control wpcf7-text\" aria-invalid=\"false\" value=\"\" type=\"text\" name=\"website_url\" \/>\n<\/div><script type='text\/javascript'>\n\n\t\t\t\t\t\tif(contactform === undefined){\n\t\t\t\t\t\t\tvar contactform = [];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar innerVal = [2589,'mail_sent_ok','Thank you for your message. It has been sent.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'mail_sent_ng','There was an error trying to send your message. Please try again later.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'validation_error','One or more fields have an error. Please check and try again.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'spam','There was an error trying to send your message. Please try again later.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'accept_terms','You must accept the terms and conditions before sending your message.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'invalid_required','The field is required.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'invalid_too_long','The field is too long.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'invalid_too_short','The field is too short.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'upload_failed','There was an unknown error uploading the file.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'upload_file_type_invalid','You are not allowed to upload files of this type.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'upload_file_too_large','The file is too big.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'upload_failed_php_error','There was an error uploading the file.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'invalid_date','The date format is incorrect.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'date_too_early','The date is before the earliest one allowed.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'date_too_late','The date is after the latest one allowed.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'invalid_number','The number format is invalid.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'number_too_small','The number is smaller than the minimum allowed.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'number_too_large','The number is larger than the maximum allowed.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'quiz_answer_not_correct','The answer to the quiz is incorrect.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'invalid_email','The e-mail address entered is invalid.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'invalid_url','The URL is invalid.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'invalid_tel','The telephone number is invalid.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'gdpr',''];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\t<\/script><div class=\"wpcf7-response-output\" aria-hidden=\"true\"><\/div>\n<\/form>\n<\/div>\n    <\/div>\n\n    <div class=\"success_disqus\">\n        Thank you for your message.\n        <span>We\u2019ll contact you shortly<\/span>.\n    <\/div>\n<\/div>\n\n<script>\n    \/\/ (function ($) {\n    function click_input() {\n        jQuery('.file_placeholder').on('click', function () {\n            jQuery(this).parent().find('input').click();\n        })\n    }\n\n    document.addEventListener(\"DOMContentLoaded\", click_input);\n\n    \/\/ })(jQuery)\n<\/script>\n\n\n<div class=\"dj-main-article-faq\" style=\"padding-top: 0px;\">\n\t\t<div class=\"dj-main-article-faq-title\">\n\t\tFrequently Asked Questions\n\t\t<\/div>\n\t\t<div class=\"dj-main-article-faq-items\">\n\t\t\t<div class=\"dj-main-article-faq-accordeon accordeon\"><dl>\n\t\t\t\t<dt>What is Docker in Python? \n\t\t\t\t<div class=\"cross\">\n\t\t\t\t<span><\/span>\n\t\t\t\t<span><\/span>\n\t\t\t\t<\/div>\n\t\t\t\t<\/dt>\n\t\t\t\t<dd>Docker is an open-source tool that automates the deployment of an application inside a software container. <br>When you develop an application, you need to provide your code along with all possible dependencies like libraries, the web server, databases, etc. You may end up in a situation when the application is working on your computer, but won\u2019t even start on the staging server, or the dev or QA\u2019s machine. This challenge can be addressed by isolating the app to make it independent of the system.<\/dd>\n\t\t\t<\/dl><dl>\n\t\t\t\t<dt>How to use Docker with Python? \n\t\t\t\t<div class=\"cross\">\n\t\t\t\t<span><\/span>\n\t\t\t\t<span><\/span>\n\t\t\t\t<\/div>\n\t\t\t\t<\/dt>\n\t\t\t\t<dd>To build a Docker image, you need to create a Dockerfile. It is a plain text file with instructions and arguments. When Dockerfile is ready, use <b>docker build<\/b> command to build a new image. After that, you can create containers and run them (using <b>docker run<\/b> command) from the image.<\/dd>\n\t\t\t<\/dl><dl>\n\t\t\t\t<dt>What are the best practices of using Docker in Python? \n\t\t\t\t<div class=\"cross\">\n\t\t\t\t<span><\/span>\n\t\t\t\t<span><\/span>\n\t\t\t\t<\/div>\n\t\t\t\t<\/dt>\n\t\t\t\t<dd>Include only necessary context \u2013 use a .dockerignore file (like .gitignore in git). Avoid installing unnecessary packages \u2013 it will consume extra disk space. Use cache - add context that changes a lot at the end of Dockerfile to utilize Docker cache effectively. Be careful with volumes - because volumes are persistent, the next container will use data from the volume created by the previous container. Use environment variables (in RUN, EXPOSE, VOLUME) - it will make your Dockerfile more flexible.<\/dd>\n\t\t\t<\/dl><dl>\n\t\t\t\t<dt>How to hire a developer with Docker for Python experience? \n\t\t\t\t<div class=\"cross\">\n\t\t\t\t<span><\/span>\n\t\t\t\t<span><\/span>\n\t\t\t\t<\/div>\n\t\t\t\t<\/dt>\n\t\t\t\t<dd>The Django Stars engineers who contributed to this guide have extensive experience developing Python and Django applications. Contact them via the contact form on this page - it is the easiest way to hire qualified and Docker-savvy developers for your project.<\/dd>\n\t\t\t<\/dl><dl>\n\t\t\t\t<dt>What are the benefits of using Docker with Python for my product? \n\t\t\t\t<div class=\"cross\">\n\t\t\t\t<span><\/span>\n\t\t\t\t<span><\/span>\n\t\t\t\t<\/div>\n\t\t\t\t<\/dt>\n\t\t\t\t<dd>The short list of benefits includes a faster development process, handy application encapsulation, the same behaviour on local machine \/ dev \/ staging \/ production servers, easy and clear monitoring, and ease to scale.<\/dd>\n\t\t\t<\/dl><\/div>\n\t\t\t<\/div>\n\t\t<\/div><br \/>\nCover image: TimFuchs203\/Shutterstock.com<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is an introductory Python Docker tutorial. By the end of this article, you will know how to use Docker on your local machine. Along with Python, we are going to run Nginx and Redis containers. Those examples assume that you are familiar with the basic concepts of those technologies. There will be lots of [&hellip;]<\/p>\n","protected":false},"author":8,"featured_media":3554,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[68,44],"tags":[9],"class_list":["post-113","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-python-engineering","category-python-django","tag-devops"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Software Development Blog &amp; IT Tech Insights | Django Stars<\/title>\n<meta name=\"description\" content=\"Full guide about uses of Docker with Python. Our team created this tutorial to share the passion and knowledge of Docker enthusiasts.\" \/>\n<link rel=\"canonical\" href=\"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/posts\/113\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Python Docker Tutorial: How to Use Docker with Python | Django Stars\" \/>\n<meta property=\"og:description\" content=\"Full guide about uses of Docker with Python. Our team created this tutorial to share the passion and knowledge of Docker enthusiasts.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/\" \/>\n<meta property=\"og:site_name\" content=\"Software Development Blog &amp; IT Tech Insights | Django Stars\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/djangostars\/\" \/>\n<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/a.ryabtsev\" \/>\n<meta property=\"article:published_time\" content=\"2018-09-27T16:38:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-09-11T16:48:02+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2021\/12\/What-is-Docker-and-How-to-Use-it-With-Python.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1440\" \/>\n\t<meta property=\"og:image:height\" content=\"620\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Alexander Ryabtsev\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@djangostars\" \/>\n<meta name=\"twitter:site\" content=\"@djangostars\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Alexander Ryabtsev\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"15 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/\"},\"author\":{\"name\":\"Alexander Ryabtsev\",\"@id\":\"https:\/\/djangostars.com\/blog\/#\/schema\/person\/f1a566bbee334235e6f57edd6930fdc1\"},\"headline\":\"Docker Tutorial: Using Docker with Python\",\"datePublished\":\"2018-09-27T16:38:00+00:00\",\"dateModified\":\"2025-09-11T16:48:02+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/\"},\"wordCount\":3167,\"commentCount\":0,\"image\":{\"@id\":\"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2021\/12\/What-is-Docker-and-How-to-Use-it-With-Python.jpg\",\"keywords\":[\"DevOps\"],\"articleSection\":[\"Expert Python \ud83d\udc0d Engineering &amp; Software Dev &amp; Tech Insights\",\"Python &amp; Django\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/\",\"url\":\"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/\",\"name\":\"Python Docker Tutorial: How to Use Docker with Python | Django Stars\",\"isPartOf\":{\"@id\":\"https:\/\/djangostars.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2021\/12\/What-is-Docker-and-How-to-Use-it-With-Python.jpg\",\"datePublished\":\"2018-09-27T16:38:00+00:00\",\"dateModified\":\"2025-09-11T16:48:02+00:00\",\"author\":{\"@id\":\"https:\/\/djangostars.com\/blog\/#\/schema\/person\/f1a566bbee334235e6f57edd6930fdc1\"},\"description\":\"Full guide about uses of Docker with Python. Our team created this tutorial to share the passion and knowledge of Docker enthusiasts.\",\"breadcrumb\":{\"@id\":\"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/#primaryimage\",\"url\":\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2021\/12\/What-is-Docker-and-How-to-Use-it-With-Python.jpg\",\"contentUrl\":\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2021\/12\/What-is-Docker-and-How-to-Use-it-With-Python.jpg\",\"width\":1440,\"height\":620,\"caption\":\"What-is-Docker-and-How-to-Use-it-With-Python\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/djangostars.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Docker Tutorial: Using Docker with Python\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/djangostars.com\/blog\/#website\",\"url\":\"https:\/\/djangostars.com\/blog\/\",\"name\":\"Software Development Blog &amp; IT Tech Insights | Django Stars\",\"description\":\"Welcome behind the scenes of software product development. We share our best practices, tech solutions, management tips, and every useful insight we\u2018ve got while working on our projects.\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/djangostars.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/djangostars.com\/blog\/#\/schema\/person\/f1a566bbee334235e6f57edd6930fdc1\",\"name\":\"Alexander Ryabtsev\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/djangostars.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/c456852d26226ecd8bc156a7339fc1f425a6774e8f9e07a977c060e2ecedebb9?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/c456852d26226ecd8bc156a7339fc1f425a6774e8f9e07a977c060e2ecedebb9?s=96&d=mm&r=g\",\"caption\":\"Alexander Ryabtsev\"},\"sameAs\":[\"https:\/\/www.facebook.com\/a.ryabtsev\",\"https:\/\/www.linkedin.com\/in\/alexander-ryabtsev\/\"],\"url\":\"https:\/\/djangostars.com\/blog\/author\/alexander-ryabtsev\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Software Development Blog &amp; IT Tech Insights | Django Stars","description":"Full guide about uses of Docker with Python. Our team created this tutorial to share the passion and knowledge of Docker enthusiasts.","canonical":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/posts\/113","og_locale":"en_US","og_type":"article","og_title":"Python Docker Tutorial: How to Use Docker with Python | Django Stars","og_description":"Full guide about uses of Docker with Python. Our team created this tutorial to share the passion and knowledge of Docker enthusiasts.","og_url":"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/","og_site_name":"Software Development Blog &amp; IT Tech Insights | Django Stars","article_publisher":"https:\/\/www.facebook.com\/djangostars\/","article_author":"https:\/\/www.facebook.com\/a.ryabtsev","article_published_time":"2018-09-27T16:38:00+00:00","article_modified_time":"2025-09-11T16:48:02+00:00","og_image":[{"width":1440,"height":620,"url":"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2021\/12\/What-is-Docker-and-How-to-Use-it-With-Python.jpg","type":"image\/jpeg"}],"author":"Alexander Ryabtsev","twitter_card":"summary_large_image","twitter_creator":"@djangostars","twitter_site":"@djangostars","twitter_misc":{"Written by":"Alexander Ryabtsev","Est. reading time":"15 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/#article","isPartOf":{"@id":"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/"},"author":{"name":"Alexander Ryabtsev","@id":"https:\/\/djangostars.com\/blog\/#\/schema\/person\/f1a566bbee334235e6f57edd6930fdc1"},"headline":"Docker Tutorial: Using Docker with Python","datePublished":"2018-09-27T16:38:00+00:00","dateModified":"2025-09-11T16:48:02+00:00","mainEntityOfPage":{"@id":"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/"},"wordCount":3167,"commentCount":0,"image":{"@id":"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/#primaryimage"},"thumbnailUrl":"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2021\/12\/What-is-Docker-and-How-to-Use-it-With-Python.jpg","keywords":["DevOps"],"articleSection":["Expert Python \ud83d\udc0d Engineering &amp; Software Dev &amp; Tech Insights","Python &amp; Django"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/","url":"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/","name":"Python Docker Tutorial: How to Use Docker with Python | Django Stars","isPartOf":{"@id":"https:\/\/djangostars.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/#primaryimage"},"image":{"@id":"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/#primaryimage"},"thumbnailUrl":"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2021\/12\/What-is-Docker-and-How-to-Use-it-With-Python.jpg","datePublished":"2018-09-27T16:38:00+00:00","dateModified":"2025-09-11T16:48:02+00:00","author":{"@id":"https:\/\/djangostars.com\/blog\/#\/schema\/person\/f1a566bbee334235e6f57edd6930fdc1"},"description":"Full guide about uses of Docker with Python. Our team created this tutorial to share the passion and knowledge of Docker enthusiasts.","breadcrumb":{"@id":"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/#primaryimage","url":"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2021\/12\/What-is-Docker-and-How-to-Use-it-With-Python.jpg","contentUrl":"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2021\/12\/What-is-Docker-and-How-to-Use-it-With-Python.jpg","width":1440,"height":620,"caption":"What-is-Docker-and-How-to-Use-it-With-Python"},{"@type":"BreadcrumbList","@id":"https:\/\/djangostars.com\/blog\/what-is-docker-and-how-to-use-it-with-python\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/djangostars.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Docker Tutorial: Using Docker with Python"}]},{"@type":"WebSite","@id":"https:\/\/djangostars.com\/blog\/#website","url":"https:\/\/djangostars.com\/blog\/","name":"Software Development Blog &amp; IT Tech Insights | Django Stars","description":"Welcome behind the scenes of software product development. We share our best practices, tech solutions, management tips, and every useful insight we\u2018ve got while working on our projects.","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/djangostars.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/djangostars.com\/blog\/#\/schema\/person\/f1a566bbee334235e6f57edd6930fdc1","name":"Alexander Ryabtsev","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/djangostars.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/c456852d26226ecd8bc156a7339fc1f425a6774e8f9e07a977c060e2ecedebb9?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/c456852d26226ecd8bc156a7339fc1f425a6774e8f9e07a977c060e2ecedebb9?s=96&d=mm&r=g","caption":"Alexander Ryabtsev"},"sameAs":["https:\/\/www.facebook.com\/a.ryabtsev","https:\/\/www.linkedin.com\/in\/alexander-ryabtsev\/"],"url":"https:\/\/djangostars.com\/blog\/author\/alexander-ryabtsev\/"}]}},"_links":{"self":[{"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/posts\/113","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/users\/8"}],"replies":[{"embeddable":true,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/comments?post=113"}],"version-history":[{"count":24,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/posts\/113\/revisions"}],"predecessor-version":[{"id":9671,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/posts\/113\/revisions\/9671"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/media\/3554"}],"wp:attachment":[{"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/media?parent=113"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/categories?post=113"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/tags?post=113"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}