{"id":8503,"date":"2023-12-26T08:00:48","date_gmt":"2023-12-26T16:00:48","guid":{"rendered":"https:\/\/live-cometml.pantheonsite.io\/?p=8503"},"modified":"2025-04-24T17:03:42","modified_gmt":"2025-04-24T17:03:42","slug":"containerization-of-machine-learning-applications","status":"publish","type":"post","link":"https:\/\/www.comet.com\/site\/blog\/containerization-of-machine-learning-applications\/","title":{"rendered":"Containerization of Machine Learning Applications"},"content":{"rendered":"\n<div class=\"lm\">\n<div class=\"ab ca\">\n<div class=\"ko ln kp lo kq lp ce lq cf lr ch bg\">\n<figure class=\"lv lw lx ly lz lm ma mb paragraph-image\">\n<div class=\"mc md ee me bg mf\" tabindex=\"0\" role=\"button\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg kt mg c alignnone\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:1000\/0*OO7o1QjrtFh696wI\" alt=\"shipping containers on a boat\" width=\"1000\" height=\"667\"><\/figure><div class=\"ls lt lu\"><picture><\/picture><\/div>\n<\/div><figcaption class=\"mh mi mj ls lt mk ml be b bf z dw\" data-selectable-paragraph=\"\">Photo by <a class=\"af mm\" href=\"https:\/\/unsplash.com\/@carrier_lost?utm_source=medium&amp;utm_medium=referral\" target=\"_blank\" rel=\"noopener ugc nofollow\">Ian Taylor<\/a> on <a class=\"af mm\" href=\"https:\/\/unsplash.com\/?utm_source=medium&amp;utm_medium=referral\" target=\"_blank\" rel=\"noopener ugc nofollow\">Unsplash<\/a><\/figcaption><\/figure>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<div class=\"ab ca\">\n<div class=\"ch bg ew ex ey ez\">\n<p id=\"f4cd\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">This article will comprehensively create, deploy, and execute machine learning application containers using the Docker tool. It will further explain the various containerization terms and the importance of this technology to the machine learning workflow. The article will contain hands-on sessions with practical coding examples as a use case. Lastly, it will discuss the best practices when working with Docker and the future of containerization.<\/p>\n<h2 id=\"2f7d\" class=\"nl nm fr be nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh oi bj\"><strong class=\"al\">What is Virtualization?<\/strong><\/h2>\n<p id=\"2a2d\" class=\"pw-post-body-paragraph mn mo fr mp b mq oj ms mt mu ok mw mx my ol na nb nc om ne nf ng on ni nj nk fk bj\" data-selectable-paragraph=\"\">To understand the concept of containerization, we need first to understand virtualization. Virtualization is the process of creating a non-physical entity that is made to appear as physical; it is a concept that dates back to the 1960s. A good example is a metaverse, where aspects of the physical world are mimicked in a simulated digital environment. In computing, virtualization creates a virtual copy of a physical IT infrastructure and resources such as hardware, application storage, network, desktop\/Operating system (OS), data, CPU\/GPU, and simulates functionality. It\u2019s more like distributing a physical machine\u02bcs&#8217;s capacity among many users or virtual environments. Virtualization has enabled cloud providers to serve their existing physical infrastructure to users. There are two forms of virtualization:<\/p>\n<ol class=\"\">\n<li id=\"1823\" class=\"mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk oo op oq bj\" data-selectable-paragraph=\"\">Virtual Machines (VMs)<\/li>\n<li id=\"6e1c\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk oo op oq bj\" data-selectable-paragraph=\"\">Containers<\/li>\n<\/ol>\n<p id=\"8c51\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\"><em class=\"ow\">We need to ask what they virtualize to understand the difference between these two types of virtualization tools.<\/em><\/p>\n<ul class=\"\">\n<li id=\"811f\" class=\"mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk ox op oq bj\" data-selectable-paragraph=\"\"><strong class=\"mp fs\">Virtual Machines (VMs)<\/strong>: VMs virtualize the underlying physical hardware\/computer using a <a class=\"af mm\" href=\"https:\/\/en.wikipedia.org\/wiki\/Hypervisor\" target=\"_blank\" rel=\"noopener ugc nofollow\">hypervisor<\/a>, thus creating several virtual computers(machines). Each virtual machine runs its OS(also guest OS) required for the respective applications, libraries, and functions separately from the other VMs. Different VMs can be run on the same physical host; for example, a parallel physical host running Linux VM, macOS VM, and Microsoft VM. Some popular VM software are VMware, VirtualBox, QEMU, Microsoft Hyper-V, and Citrix Hypervisor.<\/li>\n<\/ul>\n<figure class=\"oz pa pb pc pd lm ls lt paragraph-image\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg kt mg c alignnone\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:361\/1*oDSRxDlexkfYxOyqwCBqeQ.png\" alt=\"graphic of virtual machines\" width=\"361\" height=\"491\"><\/figure><div class=\"ls lt oy\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*oDSRxDlexkfYxOyqwCBqeQ.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*oDSRxDlexkfYxOyqwCBqeQ.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*oDSRxDlexkfYxOyqwCBqeQ.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*oDSRxDlexkfYxOyqwCBqeQ.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*oDSRxDlexkfYxOyqwCBqeQ.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*oDSRxDlexkfYxOyqwCBqeQ.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:722\/format:webp\/1*oDSRxDlexkfYxOyqwCBqeQ.png 722w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 361px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*oDSRxDlexkfYxOyqwCBqeQ.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*oDSRxDlexkfYxOyqwCBqeQ.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*oDSRxDlexkfYxOyqwCBqeQ.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*oDSRxDlexkfYxOyqwCBqeQ.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*oDSRxDlexkfYxOyqwCBqeQ.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*oDSRxDlexkfYxOyqwCBqeQ.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:722\/1*oDSRxDlexkfYxOyqwCBqeQ.png 722w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 361px\" data-testid=\"og\"><\/picture><\/div>\n<\/figure>\n<ul class=\"\">\n<li id=\"278e\" class=\"mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk ox op oq bj\" data-selectable-paragraph=\"\"><strong class=\"mp fs\">Containers<\/strong>: Containers take an alternative approach, as they package just the application alongside its binaries, libraries, and dependencies and ship it all out as one package. Containers virtualize the host OS, whereas isolated containers see a virtual kernel. However, in reality, all the containers share the host kernel. So, one OS instance can run several isolated containers. This host kernel sharing makes containers lightweight, faster to boot, efficient resource management, and more accessible and faster to deliver applications than VMs.<\/li>\n<\/ul>\n<figure class=\"oz pa pb pc pd lm ls lt paragraph-image\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg kt mg c alignnone\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:361\/1*g0YGFk5NEoYy1uohKRBZGg.png\" alt=\"graphic of containers\" width=\"361\" height=\"421\"><\/figure><div class=\"ls lt oy\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*g0YGFk5NEoYy1uohKRBZGg.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*g0YGFk5NEoYy1uohKRBZGg.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*g0YGFk5NEoYy1uohKRBZGg.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*g0YGFk5NEoYy1uohKRBZGg.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*g0YGFk5NEoYy1uohKRBZGg.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*g0YGFk5NEoYy1uohKRBZGg.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:722\/format:webp\/1*g0YGFk5NEoYy1uohKRBZGg.png 722w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 361px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*g0YGFk5NEoYy1uohKRBZGg.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*g0YGFk5NEoYy1uohKRBZGg.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*g0YGFk5NEoYy1uohKRBZGg.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*g0YGFk5NEoYy1uohKRBZGg.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*g0YGFk5NEoYy1uohKRBZGg.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*g0YGFk5NEoYy1uohKRBZGg.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:722\/1*g0YGFk5NEoYy1uohKRBZGg.png 722w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 361px\" data-testid=\"og\"><\/picture><\/div>\n<\/figure>\n<p id=\"1d09\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Containerization bundles an application with all its requirements, such as binaries, libraries, dependencies, and configuration files encapsulated in a single unit (executable) \u2014 called a container. Containerization yields portability as its containerized application is isolated and independent of the host hardware while utilizing its underlying resources like CPU and RAM. Containerization allows applications to be written once and run anywhere without concern about the machine or environment on which we run them. Despite containerization becoming a popular concept in the software industry, they have existed in different forms dating back to Unix V7, which added chroot in 1979. However, the emergence of the open-source Docker engine by Solomon Hykes in 2013 accelerated the adoption of the technology. Containerization is more portable, resource-efficient, and scalable than VMs.<\/p>\n<h2 id=\"f88f\" class=\"pe nm fr be nn pf pg ph nr pi pj pk nv my pl pm pn nc po pp pq ng pr ps pt pu bj\" data-selectable-paragraph=\"\"><strong class=\"al\">What is Docker?<\/strong><\/h2>\n<p id=\"fe92\" class=\"pw-post-body-paragraph mn mo fr mp b mq oj ms mt mu ok mw mx my ol na nb nc om ne nf ng on ni nj nk fk bj\" data-selectable-paragraph=\"\">Docker is the most popular container technology. It is an open-source tool for building, deploying, and managing containerized applications. Docker has both the open-source variant and the commercial variant.<\/p>\n<p id=\"2469\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Docker\u2019s container technology is powered by the Linux kernel, utilizing features such as control groups (cgroups) and kernel namespaces to create and manage loosely isolated environments. The cgroups are also known as process containers which monitor and manage resources such as CPU, disk IO, network, and memory for a collection of processes. At the same time, namespaces isolate the process groups and resources from each other. Each docker container has its set of processes and namespace; Docker also utilizes a network driver (libnetwork) for network isolation and communication between containers. Since Docker depends on the Linux kernel features, Windows and Mac systems can\u2019t run the Linux containers directly. Docker tries to solve this compatibility issue with the Docker Desktop, where its internal working involves installing a micro Linux VM (Guest OS) on which it runs the containers. So rather than the VM using numerous Guest OS, this Docker Desktop install on a single VM (micro Linux VM) runs all containers and executes Docker commands. So, in general, Docker can\u2019t run all operating systems. This Linux VM plugs into the Host OS and gives containers access to file systems and networking resources.<\/p>\n<h2 id=\"9089\" class=\"nl nm fr be nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh oi bj\"><strong class=\"al\">Why Use Docker for Machine Learning?<\/strong><\/h2>\n<p id=\"8b14\" class=\"pw-post-body-paragraph mn mo fr mp b mq oj ms mt mu ok mw mx my ol na nb nc om ne nf ng on ni nj nk fk bj\" data-selectable-paragraph=\"\">The machine learning (ML) lifecycle defines steps to derive values to meet business objectives using ML and artificial intelligence (AI). These steps include defining business and project objectives, acquiring and exploring data, modeling the data with various algorithms, interpreting and communicating the project outcome, and implementing and maintaining the project. In today\u2019s agile environment, it is essential to perform multiple iterations and experiments, respond quickly to changes, and successfully deploy to deliver value and satisfy business requirements.<\/p>\n<p id=\"21db\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Docker creates isolated environments, making the development and deployment setup seamless as it bundles applications in containers. Docker makes machine learning workloads portable and reproducible. Virtual environments created by <a class=\"af mm\" href=\"https:\/\/docs.conda.io\/en\/latest\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">conda<\/a> and <a class=\"af mm\" href=\"https:\/\/virtualenv.pypa.io\/en\/latest\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">virtualenv<\/a> addresses are portable and reproducible. Yes, they do, but partially. These Python virtual environments encapsulate and manage Python dependencies, while Docker encapsulates the project\u2019s dependency stack down to the host OS. So, you are sharing your entire development environment rather than sharing packaged dependencies and source code. Docker creates isolated environments, making the development and deployment setup seamless as it bundles applications in containers. Docker makes machine learning workloads portable and reproducible. You can argue that virtual environments created by conda and virtualenv addresses are portable and reproducible. Yes, they do, but partially. These Python virtual environments encapsulate and manage Python dependencies.<\/p>\n<p id=\"9ed2\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">In contrast, Docker encapsulates the project\u2019s entire dependency stack down to the host OS (and avoids issues of projects working on your machine and crashing on other people\u2019s machines). So, you are sharing your entire development environment rather than sharing packaged dependencies and source code. Docker enables collaboration across machine learning projects while keeping consistency, portability, and dependency management at its core. Creating a virtual environment inside a Docker container makes little sense, as Docker provides the required isolations.<\/p>\n<p id=\"65a1\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Demystifying some terminologies:<\/p>\n<ul class=\"\">\n<li id=\"4398\" class=\"mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk ox op oq bj\" data-selectable-paragraph=\"\"><strong class=\"mp fs\">Dockerfile<\/strong>: This human-readable text file contains all the commands or instructions to build docker images. It can be seen as a recipe specifying the required ingredients for the application.<\/li>\n<li id=\"048e\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\"><strong class=\"mp fs\">Docker Images<\/strong>: This template contains the source code, installations, and dependencies required to set up a fully operational container environment. Docker images are layers (collections of files that bundle the source code, installations, and required dependencies). These image layers follow a hierarchy, as each layer depends on the layer immediately below it.<\/li>\n<li id=\"388a\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\"><strong class=\"mp fs\">Docker Containers<\/strong>: This is a running instance of the Docker image, which serves as the virtual isolation environment that packages the application and all the requirements to run the application. Docker registry: This repository stores and distributes Docker images with specific names and versions. They are public and private Docker registries; Docker Hub is a public registry, and Docker, by default, is configured to look for images in Docker Hub.<\/li>\n<li id=\"b135\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\"><strong class=\"mp fs\">Docker Engine<\/strong>: This is the core of the Docker containerization technology, which acts as a client-server application. The Docker daemon (dockerd) as the server and the client side have been accessed by the command line interface (CLI) client (Docker). The Docker Engine handles interactions with the kernel and makes system calls for managing and creating containers. Docker APIs interact with the Docker daemon through the CLI commands or scripting.<\/li>\n<\/ul>\n<h2 id=\"8c98\" class=\"nl nm fr be nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh oi bj\"><strong class=\"al\">Use Case<\/strong><\/h2>\n<p id=\"5cf0\" class=\"pw-post-body-paragraph mn mo fr mp b mq oj ms mt mu ok mw mx my ol na nb nc om ne nf ng on ni nj nk fk bj\" data-selectable-paragraph=\"\">To drive the understanding of the containerization of machine learning applications, we will build an end-to-end machine learning classification application. The sample data for this project is E-Commerce Shipping data found on Kaggle to predict whether product shipments were delivered on time. The dataset used for model building contained 10999 observations of 12 variables. The data includes the following information:<\/p>\n<ul class=\"\">\n<li id=\"eb47\" class=\"mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">ID: Customer ID number.<\/li>\n<li id=\"bca7\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Warehouse block: The company warehouse is segmented into blocks such as A, B, C, D, and F.<\/li>\n<li id=\"1078\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Mode of shipment: Company modes of shipping are ship, flight, and road.<\/li>\n<li id=\"5903\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Customer care calls: Number of customer calls for shipment inquiries.<\/li>\n<li id=\"cae1\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Customer rating: Customers\u2019 rating for shipping. From lowest(1) to highest(5).<\/li>\n<li id=\"b4b5\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Cost of the product: Shipped products cost (USD).<\/li>\n<li id=\"d872\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Prior purchases: Customer number of previous purchases.<\/li>\n<li id=\"c4a7\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Product importance: Company importance category of products(low, medium, and high).<\/li>\n<li id=\"b01a\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Gender: Customers\u2019 gender.<\/li>\n<li id=\"1061\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Discount offered: Discount offered on that specific product.<\/li>\n<li id=\"4d75\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Weight in gms: Weight of products being shipped (grams).<\/li>\n<li id=\"4093\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Reached on time: This is the target variable that indicates whether the product arrived on time, as 0 and 1, respectively.<\/li>\n<\/ul>\n<h2 id=\"3495\" class=\"nl nm fr be nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh oi bj\">Prerequisite<\/h2>\n<ul class=\"\">\n<li id=\"6103\" class=\"mn mo fr mp b mq oj ms mt mu ok mw mx my ol na nb nc om ne nf ng on ni nj nk ox op oq bj\" data-selectable-paragraph=\"\"><a class=\"af mm\" href=\"https:\/\/www.anaconda.com\/products\/distribution\" target=\"_blank\" rel=\"noopener ugc nofollow\">Python 3.8<\/a> or newer.<\/li>\n<li id=\"1253\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">The <a class=\"af mm\" href=\"https:\/\/www.anaconda.com\/products\/distribution\" target=\"_blank\" rel=\"noopener ugc nofollow\">Anaconda distribution<\/a> includes several valuable libraries for data science.<\/li>\n<li id=\"a76e\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\"><a class=\"af mm\" href=\"https:\/\/docs.docker.com\/engine\/install\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">Docker<\/a> installation.<\/li>\n<li id=\"358c\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\"><a class=\"af mm\" href=\"https:\/\/signup.heroku.com\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">Heroku<\/a> Account \/ <a class=\"af mm\" href=\"https:\/\/devcenter.heroku.com\/articles\/heroku-cli\" target=\"_blank\" rel=\"noopener ugc nofollow\">Heroku CLI<\/a> installation<\/li>\n<li id=\"9f0c\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Basic knowledge of <a class=\"af mm\" href=\"https:\/\/flask.palletsprojects.com\/en\/2.1.x\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">Flask<\/a>, <a class=\"af mm\" href=\"https:\/\/en.wikipedia.org\/wiki\/HTML\" target=\"_blank\" rel=\"noopener ugc nofollow\">HTML<\/a>, and <a class=\"af mm\" href=\"https:\/\/en.wikipedia.org\/wiki\/CSS\" target=\"_blank\" rel=\"noopener ugc nofollow\">CSS<\/a>.<\/li>\n<li id=\"833a\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Basic understanding of building machine learning models.<\/li>\n<\/ul>\n<h2 id=\"821d\" class=\"nl nm fr be nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh oi bj\"><strong class=\"al\">Machine Learning Model Development<\/strong><\/h2>\n<p id=\"cb45\" class=\"pw-post-body-paragraph mn mo fr mp b mq oj ms mt mu ok mw mx my ol na nb nc om ne nf ng on ni nj nk fk bj\" data-selectable-paragraph=\"\">Let&#8217;s initialize the project by creating a directory and setting up a Python virtual environment for storing the various Python dependencies. We can make the directory for our project from our terminal as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"6686\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\"><span class=\"hljs-built_in\">mkdir<\/span> containerized-app<\/span><\/pre>\n<p id=\"9f3f\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Next, after creating the containerized-app folder, we change the working directory to the created folder as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"9f45\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\"><span class=\"hljs-built_in\">cd<\/span> containerized-app<\/span><\/pre>\n<p id=\"550e\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Next, we create a Python virtual environment to manage the project\u2019s Python dependencies as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"e5d7\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">python3 -m venv venv<\/span><\/pre>\n<p id=\"cf96\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">The code to activate the virtual environment depends on your local machine. For macOS and Linux, run:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"062e\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\"><span class=\"hljs-built_in\">source<\/span> venv\/bin\/activate<\/span><\/pre>\n<p id=\"f4a7\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">If you are using a Windows computer, activate the environment as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"cada\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">venv\\<span class=\"hljs-title.class\">Scripts<\/span>\\activate<\/span><\/pre>\n<p id=\"e92d\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">These commands create and activate a virtual environment called env so that the project will use packages installed and loaded from this environment instead of system-level packages.<\/p>\n<p id=\"26ac\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">The file structure at the beginning of this project(inside the containerized-app folder, so go ahead and create the app and ml-dev directories) should look like this:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"17e5\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">.\n\u251c\u2500\u2500 app\n\u251c\u2500\u2500 ml-dev\n\u2514\u2500\u2500 venv<\/span><\/pre>\n<p id=\"bfb3\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">The app directory will contain our flask application, the ml-dev directory will contain our dataset and Jupyter notebook, and the venv virtual environment directory that manages our project Python dependencies.<\/p>\n<h2 id=\"1308\" class=\"nl nm fr be nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh oi bj\">Install Required Packages<\/h2>\n<p id=\"735b\" class=\"pw-post-body-paragraph mn mo fr mp b mq oj ms mt mu ok mw mx my ol na nb nc om ne nf ng on ni nj nk fk bj\" data-selectable-paragraph=\"\">Next, you install all the packages needed for this project. In your new virtual environment, install the following packages (which include libraries and dependencies):<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"aa48\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">pip3 install jupyterlab==3.4.3 Flask==2.1.2 gunicorn==20.1.0\nxgboost==1.6.1 scikit-learn==1.1.1 matplotlib==3.5.2 missingno==0.5.1<\/span><\/pre>\n<p id=\"9c23\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Here are some details about these packages:<\/p>\n<ul class=\"\">\n<li id=\"3c07\" class=\"mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk ox op oq bj\" data-selectable-paragraph=\"\"><a class=\"af mm\" href=\"https:\/\/jupyter.org\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">jupyterlab<\/a> is for model building and data exploration.<\/li>\n<li id=\"2264\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\"><a class=\"af mm\" href=\"https:\/\/flask.palletsprojects.com\/en\/1.1.x\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">flask<\/a> is used for creating the application server and pages.<\/li>\n<li id=\"19fd\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\"><a class=\"af mm\" href=\"https:\/\/gunicorn.org\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">gunicorn<\/a> is for serving a production-ready Flask application.<\/li>\n<li id=\"d5fe\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\"><a class=\"af mm\" href=\"https:\/\/catboost.ai\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">catboost<\/a> is the machine learning algorithm for model building.<\/li>\n<li id=\"6a18\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\"><a class=\"af mm\" href=\"https:\/\/scikit-learn.org\/stable\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">scikit-learn<\/a> is a machine learning toolkit.<\/li>\n<li id=\"d3df\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\"><a class=\"af mm\" href=\"https:\/\/matplotlib.org\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">matplotlib<\/a> is for data visualization.<\/li>\n<li id=\"a089\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\"><a class=\"af mm\" href=\"https:\/\/github.com\/ResidentMario\/missingno\" target=\"_blank\" rel=\"noopener ugc nofollow\">missingno<\/a> is for missing values visualization.<\/li>\n<\/ul>\n<p id=\"b974\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">If you haven\u2019t tried to create the app and ml-dev directories, we can do that from our terminal in the containerized-app directory as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"1399\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\"><span class=\"hljs-built_in\">mkdir<\/span> app ml-dev<\/span><\/pre>\n<p id=\"18da\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Then, change the directory to the ml-dev for our machine learning development task as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"cd84\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\"><span class=\"hljs-built_in\">cd<\/span> ml-dev<\/span><\/pre>\n<p id=\"cb3b\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">The content of the ml-dev folder should look somewhat like this:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"f9e8\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">.\n\u251c\u2500\u2500 <span class=\"hljs-keyword\">data<\/span>\n\u2502   \u2514\u2500\u2500 shipping_data.csv\n\u2514\u2500\u2500 dev-notebook.ipynb<\/span><\/pre>\n<p id=\"b5f5\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Where the data directory contains the download use case data from Kaggle.<\/p>\n<p id=\"5a54\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Start your Jupyter lab by running:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"5a9b\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">jupyter lab<\/span><\/pre>\n<p id=\"e2e6\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">This command opens the popular Jupyter Lab interface in your web browser. Create a new notebook named dev-notebook, where we will carry out interactive data exploration and model building. First, we import the necessary libraries for this project and read the dataset as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"d9ea\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\"><span class=\"hljs-comment\"># neccessary imports<\/span>\n<span class=\"hljs-keyword\">import<\/span> pandas <span class=\"hljs-keyword\">as<\/span> pd\n<span class=\"hljs-keyword\">import<\/span> numpy <span class=\"hljs-keyword\">as<\/span> np\n<span class=\"hljs-keyword\">import<\/span> pickle\n<span class=\"hljs-keyword\">import<\/span> matplotlib.pyplot <span class=\"hljs-keyword\">as<\/span> plt\n<span class=\"hljs-keyword\">import<\/span> seaborn <span class=\"hljs-keyword\">as<\/span> sns\n<span class=\"hljs-keyword\">import<\/span> missingno <span class=\"hljs-keyword\">as<\/span> msno\n<span class=\"hljs-keyword\">from<\/span> sklearn.pipeline <span class=\"hljs-keyword\">import<\/span> Pipeline\n<span class=\"hljs-keyword\">from<\/span> sklearn.compose <span class=\"hljs-keyword\">import<\/span> ColumnTransformer\n<span class=\"hljs-keyword\">from<\/span> sklearn.preprocessing <span class=\"hljs-keyword\">import<\/span> OrdinalEncoder, OneHotEncoder,\nMinMaxScaler\n<span class=\"hljs-keyword\">from<\/span> sklearn.model_selection <span class=\"hljs-keyword\">import<\/span> train_test_split\n<span class=\"hljs-keyword\">from<\/span> sklearn.metrics <span class=\"hljs-keyword\">import<\/span> roc_auc_score\n<span class=\"hljs-keyword\">from<\/span> xgboost <span class=\"hljs-keyword\">import<\/span> XGBClassifier\n\n<span class=\"hljs-comment\"># Load data<\/span>\ndata = pd.read_csv(<span class=\"hljs-string\">'data\/shipping_data.csv'<\/span>)\nfeature_names = data.columns.tolist()\ntarget = <span class=\"hljs-string\">'Reached.on.Time_Y.N'<\/span><\/span><\/pre>\n<p id=\"abf6\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">The dataset has no missing instances and has 10999 rows &amp; 12 features, including the target. The dataset has four categorical features, classified into nominal and ordinal. Next, we will create a pipeline (aid cleaner code) to take care of our preprocessing procedures that involve feature scaling (normalization) and categorical handling (ordinal and one-hot encoding for ordinal and nominal features, respectively), as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"4fff\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\"><span class=\"hljs-comment\"># Re-categorical categories into nominal and ordinal categorical features <\/span>\n<span class=\"hljs-attr\">nominal_categroical_features<\/span> = [<span class=\"hljs-string\">'Mode_of_Shipment'<\/span>, <span class=\"hljs-string\">'Gender'<\/span>]\n<span class=\"hljs-attr\">ordinal_categorical_features<\/span> = [<span class=\"hljs-string\">'Warehouse_block'<\/span>, <span class=\"hljs-string\">'Product_importance'<\/span>]\n\n<span class=\"hljs-comment\"># Create preprocessing pipeline<\/span>\n<span class=\"hljs-attr\">numeric_pipeline<\/span> = Pipeline(steps=[(<span class=\"hljs-string\">'scale'<\/span>, MinMaxScaler())])\n<span class=\"hljs-attr\">warehouse_block_order<\/span> = [<span class=\"hljs-string\">'A'<\/span>, <span class=\"hljs-string\">'B'<\/span>, <span class=\"hljs-string\">'C'<\/span>, <span class=\"hljs-string\">'D'<\/span>, <span class=\"hljs-string\">'F'<\/span>]\n<span class=\"hljs-attr\">product_importance_order<\/span> = [<span class=\"hljs-string\">'low'<\/span>, <span class=\"hljs-string\">'medium'<\/span>, <span class=\"hljs-string\">'high'<\/span>]\n<span class=\"hljs-attr\">ordinal_categorical_pipeline<\/span> = Pipeline(steps=[(<span class=\"hljs-string\">'ordinal encoding'<\/span>,\nOrdinalEncoder(categories=[warehouse_block_order,\nproduct_importance_order],handle_unknown=<span class=\"hljs-string\">\"use_encoded_value\"<\/span>,\nunknown_value=-<span class=\"hljs-number\">1<\/span>))])\n<span class=\"hljs-attr\">nominal_categorical_pipeline<\/span> = Pipeline(steps=[(<span class=\"hljs-string\">'one-hot encoding'<\/span>,\n<span class=\"hljs-literal\">On<\/span>eHotEncoder(handle_unknown=<span class=\"hljs-string\">'ignore'<\/span>, sparse=<span class=\"hljs-literal\">False<\/span>, drop=<span class=\"hljs-string\">'first'<\/span>))])\n\n<span class=\"hljs-comment\"># Compiling pipeline steps<\/span>\n<span class=\"hljs-attr\">preprocessing_pipeline<\/span> = ColumnTransformer(transformers=[\n    (<span class=\"hljs-string\">'number'<\/span>, numeric_pipeline, numerical_features),\n    (<span class=\"hljs-string\">'ordinal_category'<\/span>, ordinal_categorical_pipeline,\nordinal_categorical_features),\n    (<span class=\"hljs-string\">'nominal_category'<\/span>, nominal_categorical_pipeline,\nnominal_categroical_features)])\n\n<span class=\"hljs-comment\"># Compile model pipeline<\/span>\n<span class=\"hljs-attr\">xgboost_instance<\/span> = XGBClassifier()\n<span class=\"hljs-attr\">full_pipeline<\/span> = Pipeline(steps=[\n    (<span class=\"hljs-string\">'preprocess'<\/span>, preprocessing_pipeline),\n    (<span class=\"hljs-string\">'model'<\/span>, xgboost_instance)])\n\n<span class=\"hljs-attr\">_<\/span> = full_pipeline.fit(X_train, y_train)<\/span><\/pre>\n<p id=\"2124\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Let\u2019s evaluate the performance of the model by its prediction.<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"e910\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\"><span class=\"hljs-comment\"># Making prediction<\/span>\ny_pred = full_pipeline.predict_proba(X_test)\n<span class=\"hljs-comment\"># Evaluating results<\/span>\n<span class=\"hljs-built_in\">print<\/span>(<span class=\"hljs-string\">'ROC AUC score: '<\/span>, roc_auc_score(y_test, y_pred[:, 1]))<\/span><\/pre>\n<p id=\"a980\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Our model yielded an ROC AUC score of 0.74, which is satisfactory as ROC scores between 0.7 and 0.8 are considered acceptable. The model can be improved with more comprehensive preprocessing, hyperparameter tuning, and algorithm choices.<\/p>\n<p id=\"f330\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Lastly, we need to save the model pipeline as a pickle file to the app directory so our flask application can communicate with it easily as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"a46c\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\"><span class=\"hljs-comment\"># create an iterator object with write permission - pipeline.pkl <\/span>\n<span class=\"hljs-keyword\">with<\/span> <span class=\"hljs-built_in\">open<\/span>(<span class=\"hljs-string\">'..\/app\/pipeline.pkl'<\/span>, <span class=\"hljs-string\">'wb'<\/span>) <span class=\"hljs-keyword\">as<\/span> file:\n    pickle.dump(full_pipeline, file)<\/span><\/pre>\n<h2 id=\"f101\" class=\"nl nm fr be nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh oi bj\">Creating Machine Learning Application with Flask<\/h2>\n<p id=\"ee30\" class=\"pw-post-body-paragraph mn mo fr mp b mq oj ms mt mu ok mw mx my ol na nb nc om ne nf ng on ni nj nk fk bj\" data-selectable-paragraph=\"\">Flask is a Python web application framework that we will use to create a simple web application that enables interactions with a machine learning model pipeline. To commence building our web application, we will exit the ml-dev directory to the containerized-app directory as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"9a73\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\"><span class=\"hljs-built_in\">cd<\/span> ..<\/span><\/pre>\n<p id=\"25a9\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">And change our directory to the app directory that will contain files and directories to build our application:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"87aa\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\"><span class=\"hljs-built_in\">cd<\/span> app<\/span><\/pre>\n<p id=\"7ce7\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Let\u2019s look into our app directory structure to give a good overview of our project scope and functionalities. The app directory is as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"a726\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">.\n\u251c\u2500\u2500 Dockerfile\n\u251c\u2500\u2500 Procfile\n\u251c\u2500\u2500 app.py\n\u251c\u2500\u2500 pipeline.pkl\n\u251c\u2500\u2500 requirements.txt\n\u251c\u2500\u2500 <span class=\"hljs-type\">static<\/span>\n\u2502   \u251c\u2500\u2500 containers.jpg\n\u2502   \u2514\u2500\u2500 style.css\n\u251c\u2500\u2500 templates\n\u2502   \u2514\u2500\u2500 index.html\n\u2514\u2500\u2500 wsgi.py<\/span><\/pre>\n<p id=\"ad67\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Let\u2019s have a quick summary of the functionality of the various files and folders outlined above:<\/p>\n<ul class=\"\">\n<li id=\"a55c\" class=\"mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">templates: This folder contains assets describing our application\u2019s main(home) page. It includes an index.html file, which defines our application\u2019s web page structure and content.<\/li>\n<li id=\"1881\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">static: This folder contains assets used by templates, in this case, our index.html. These files include CSS stylesheets, javascript files, and images to add design and functionality.<\/li>\n<li id=\"c6b6\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">app.py: This script is our main application app that utilizes the Flask framework and refers to both the templates and static folders to build our application user interface (UI)<\/li>\n<li id=\"16aa\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">pipeline.pkl: This is the classification model pipeline we developed in the model development section. The pickled pipeline will be applied to new data instances (user inputs) to generate predictions.<\/li>\n<li id=\"9c29\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">wsgi.py: This script serves our flask application in the development server to a production server using Gunicorn.<\/li>\n<li id=\"a7d0\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Dockerfile: This file contains all the instructions required to containerize our flask application adequately.<\/li>\n<li id=\"881a\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Procfile: This file is required when deploying our application to Heroku (a public server so our application can be available online).<\/li>\n<li id=\"8cc4\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">requirements.txt: This file records and manages all the Python dependencies required for this project.<\/li>\n<\/ul>\n<p id=\"ac39\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">First, let\u2019s record all our virtual environment\u2019s current package list into a text file requirements.txt at the project\u2019s base directory by running the following on our terminal:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"8bc8\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">pip3 freeze &gt; requirements.<span class=\"hljs-property\">txt<\/span><\/span><\/pre>\n<p id=\"284c\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Next, we set up Git for version control to track all the changes in your application by initializing the Git repository to track changes in the project files as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"244a\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">git <span class=\"hljs-keyword\">init<\/span><\/span><\/pre>\n<p id=\"df3a\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Next, let\u2019s create the app.py and input the following to get started building our application:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"62c2\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\"><span class=\"hljs-keyword\">import<\/span> os                   <span class=\"hljs-comment\"># For interacting with the file system<\/span>\n<span class=\"hljs-keyword\">import<\/span> pandas <span class=\"hljs-keyword\">as<\/span> pd         <span class=\"hljs-comment\"># For data wrangling operations<\/span>\n<span class=\"hljs-keyword\">import<\/span> pickle               <span class=\"hljs-comment\"># For loading the pickled model pipeline <\/span>\n<span class=\"hljs-keyword\">from<\/span> flask <span class=\"hljs-keyword\">import<\/span> Flask, render_template,  request, url_for             <span class=\"hljs-comment\"># <\/span>\nFor web application development\n\napp = Flask(__name__)\n\n<span class=\"hljs-comment\"># Home route<\/span>\n<span class=\"hljs-meta\">@app.route(<span class=\"hljs-params\"><span class=\"hljs-string\">\"\/\"<\/span>, methods=[<span class=\"hljs-string\">'GET'<\/span>, <span class=\"hljs-string\">'POST'<\/span>]<\/span>) <\/span>\n<span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title.function\">home<\/span>():\n    <span class=\"hljs-keyword\">return<\/span> render_template(<span class=\"hljs-string\">'index.html'<\/span>)        <span class=\"hljs-comment\"># render_template helps <\/span>\ngenerate output of our HTML file\n\n<span class=\"hljs-keyword\">if<\/span> __name__ == <span class=\"hljs-string\">\"__main__\"<\/span>:\n    port = <span class=\"hljs-built_in\">int<\/span>(os.environ.get(<span class=\"hljs-string\">'PORT'<\/span>, <span class=\"hljs-number\">5000<\/span>))\n    app.run(host = <span class=\"hljs-string\">'0.0.0.0'<\/span>, port = port)<\/span><\/pre>\n<p id=\"aa70\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Our flask app \u2014 app.py starts by creating a flask object representing our app and then sets the home route view to our home page at index.html. The Flask app comprises a simple form that gets all the feature inputs defined by the index.html file and styled using CSS and <a class=\"af mm\" href=\"https:\/\/getbootstrap.com\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">Bootstrap<\/a>. Bootstrap is a popular CSS framework for developing responsive and mobile-first web apps, and it\u2019s easy to use with basic knowledge of HTML and CSS.<\/p>\n<p id=\"59b2\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Flask is a great way to build Python applications quickly, but its inbuilt server is not production-ready, as it can only serve one person at a time. The Flask development server is intended for use only during local development as it is not particularly efficient, stable, and secure to run in the production environment. With this in mind, we must specify the host to 0.0.0.0 as the default refers to the local host (127.0.0.1). Changing the host to 0.0.0.0 makes the server publicly available, thus listening on all public IPs. Lastly, the application is bound to port 5000.<\/p>\n<p id=\"7265\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Next, let&#8217;s define the application UI by describing the structure of our web app, which is depicted with the HTML containers (block of content) with their respective classes below:<\/p>\n<figure class=\"oz pa pb pc pd lm ls lt paragraph-image\">\n<div class=\"mc md ee me bg mf\" tabindex=\"0\" role=\"button\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg kt mg c alignnone\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:700\/1*BVXdH4GuuNntfxFQlcwpFw.png\" alt=\"HTML containers with their respective classes\" width=\"700\" height=\"384\"><\/figure><div class=\"ls lt qe\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*BVXdH4GuuNntfxFQlcwpFw.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*BVXdH4GuuNntfxFQlcwpFw.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*BVXdH4GuuNntfxFQlcwpFw.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*BVXdH4GuuNntfxFQlcwpFw.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*BVXdH4GuuNntfxFQlcwpFw.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*BVXdH4GuuNntfxFQlcwpFw.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*BVXdH4GuuNntfxFQlcwpFw.png 1400w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*BVXdH4GuuNntfxFQlcwpFw.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*BVXdH4GuuNntfxFQlcwpFw.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*BVXdH4GuuNntfxFQlcwpFw.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*BVXdH4GuuNntfxFQlcwpFw.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*BVXdH4GuuNntfxFQlcwpFw.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*BVXdH4GuuNntfxFQlcwpFw.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*BVXdH4GuuNntfxFQlcwpFw.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\" data-testid=\"og\"><\/picture><\/div>\n<\/div>\n<\/figure>\n<p id=\"e751\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Following the structure above, the index.html file should contain the following:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"42e4\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\"><span class=\"hljs-meta\">&lt;!DOCTYPE <span class=\"hljs-keyword\">html<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">html<\/span> <span class=\"hljs-attr\">lang<\/span>=<span class=\"hljs-string\">\"en\"<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">head<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">charset<\/span>=<span class=\"hljs-string\">\"UTF-8\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">http-equiv<\/span>=<span class=\"hljs-string\">\"X-UA-Compatible\"<\/span> <span class=\"hljs-attr\">content<\/span>=<span class=\"hljs-string\">\"IE=edge\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"viewport\"<\/span> <span class=\"hljs-attr\">content<\/span>=<span class=\"hljs-string\">\"width=device-width, initial-scale=1.0\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">title<\/span>&gt;<\/span>E-Commerce Shipping tracking app<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">title<\/span>&gt;<\/span>\n    <span class=\"hljs-comment\">&lt;!-- Importing Bootstrap CSS --&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span>\n<span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"https:\/\/cdn.jsdelivr.net\/npm\/bootstrap@5.0.2\/dist\/css\/bootstrap.min.\ncss\"<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"stylesheet\"<\/span> <span class=\"hljs-attr\">integrity<\/span>=<span class=\"hljs-string\">\"sha384-\nEVSTQN3\/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC\"<\/span>\n<span class=\"hljs-attr\">crossorigin<\/span>=<span class=\"hljs-string\">\"anonymous\"<\/span>&gt;<\/span>\n     <span class=\"hljs-comment\">&lt;!-- Importing Personal CSS --&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"stylesheet\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"..\/static\/style.css\"<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">head<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"container\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"about-app\"<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>E-Commerce Shipping web app that predicts whether a\nproduct reach on time or not<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"portal\"<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"app-image\"<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"{{url_for('static',\nfilename='containers.jpg')}}\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"image\"<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"app-form\"<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-header\"<\/span>&gt;<\/span>Product Shipment Tracking details:\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">form<\/span> <span class=\"hljs-attr\">action<\/span>=<span class=\"hljs-string\">\"\/predict\"<\/span> <span class=\"hljs-attr\">method<\/span>=<span class=\"hljs-string\">\"POST\"<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"input-group input-group-sm mb-3\"<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"input-group-text\"<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"inputGroup-\nsizing-sm\"<\/span>&gt;<\/span>ID<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"form-id\"<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"number\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-\ncontrol\"<\/span> <span class=\"hljs-attr\">aria-label<\/span>=<span class=\"hljs-string\">\"Sizing example input\"<\/span> <span class=\"hljs-attr\">aria-describedby<\/span>=<span class=\"hljs-string\">\"inputGroup-\nsizing-sm\"<\/span> <span class=\"hljs-attr\">required<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">select<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-select form-select-sm mb-3\"<\/span>\n<span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"form-warehouse-block\"<\/span> <span class=\"hljs-attr\">required<\/span> <span class=\"hljs-attr\">aria-label<\/span>=<span class=\"hljs-string\">\".form-select-sm example\"<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"\"<\/span>&gt;<\/span>Warehouse block<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"A\"<\/span>&gt;<\/span>A<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"B\"<\/span>&gt;<\/span>B<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"C\"<\/span>&gt;<\/span>C<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"D\"<\/span>&gt;<\/span>D<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"F\"<\/span>&gt;<\/span>F<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">select<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">select<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-select form-select-sm mb-3\"<\/span>\n<span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"form-shipment-mode\"<\/span> <span class=\"hljs-attr\">aria-label<\/span>=<span class=\"hljs-string\">\".form-select-sm example\"<\/span> <span class=\"hljs-attr\">required<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"\"<\/span>&gt;<\/span>Mode of shipment<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"Flight\"<\/span>&gt;<\/span>Flight<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"Ship\"<\/span>&gt;<\/span>Ship<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"Road\"<\/span>&gt;<\/span>Road<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">select<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"input-group input-group-sm mb-3\"<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"input-group-text\"<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"inputGroup-\nsizing-sm\"<\/span>&gt;<\/span>Customer care calls<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"number\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-control\"<\/span>\n<span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"form-customer-care-calls\"<\/span> <span class=\"hljs-attr\">aria-label<\/span>=<span class=\"hljs-string\">\"Sizing example input\"<\/span> <span class=\"hljs-attr\">aria-<\/span>\n<span class=\"hljs-attr\">describedby<\/span>=<span class=\"hljs-string\">\"inputGroup-sizing-sm\"<\/span> <span class=\"hljs-attr\">required<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">select<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-select form-select-sm mb-3\"<\/span>\n<span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"form-customer-ratings\"<\/span> <span class=\"hljs-attr\">aria-label<\/span>=<span class=\"hljs-string\">\".form-select-sm example\"<\/span>\n<span class=\"hljs-attr\">required<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"\"<\/span>&gt;<\/span>Customer ratings<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"1\"<\/span>&gt;<\/span>Worst<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"2\"<\/span>&gt;<\/span>Bad<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"3\"<\/span>&gt;<\/span>Neutral<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"4\"<\/span>&gt;<\/span>Good<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"5\"<\/span>&gt;<\/span>Best<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">select<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"input-group input-group-sm  mb-3\"<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"input-group-text\"<\/span>&gt;<\/span>Cost of\nproduct<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"input-group-text\"<\/span>&gt;<\/span>$<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"number\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-control\"<\/span>\n<span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"form_product_cost\"<\/span> <span class=\"hljs-attr\">aria-label<\/span>=<span class=\"hljs-string\">\"Dollar amount (with dot and two\ndecimal places)\"<\/span> <span class=\"hljs-attr\">required<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"input-group input-group-sm mb-3\"<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"input-group-text\"<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"inputGroup-\nsizing-sm\"<\/span>&gt;<\/span>Prior purchases<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"number\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-control\"<\/span>\n<span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"form-prior-purchases\"<\/span> <span class=\"hljs-attr\">aria-label<\/span>=<span class=\"hljs-string\">\"Sizing example input\"<\/span> <span class=\"hljs-attr\">aria-<\/span>\n<span class=\"hljs-attr\">describedby<\/span>=<span class=\"hljs-string\">\"inputGroup-sizing-sm\"<\/span> <span class=\"hljs-attr\">required<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">select<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-select form-select-sm mb-3\"<\/span>\n<span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"form_product_importance\"<\/span> <span class=\"hljs-attr\">aria-label<\/span>=<span class=\"hljs-string\">\".form-select-sm example\"<\/span>\n<span class=\"hljs-attr\">required<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"\"<\/span>&gt;<\/span>Product importance<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"low\"<\/span>&gt;<\/span>Low<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"medium\"<\/span>&gt;<\/span>Medium<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"high\"<\/span>&gt;<\/span>High<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">select<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-check  form-check-inline\"<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"radio\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-check-input\"<\/span>\n<span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"validationFormCheck2\"<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"form-gender\"<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"M\"<\/span> <span class=\"hljs-attr\">required<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">label<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-check-label\"<\/span>\n<span class=\"hljs-attr\">for<\/span>=<span class=\"hljs-string\">\"validationFormCheck2\"<\/span>&gt;<\/span>Male<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">label<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-check form-check-inline\"<\/span>&gt;<\/span>\n                       <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"radio\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-check-input\"<\/span>\n<span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"validationFormCheck3\"<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"form-gender\"<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"F\"<\/span> <span class=\"hljs-attr\">required<\/span>&gt;<\/span>\n                       <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">label<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-check-label\"<\/span>\n<span class=\"hljs-attr\">for<\/span>=<span class=\"hljs-string\">\"validationFormCheck3\"<\/span>&gt;<\/span>Female<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">label<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"input-group input-group-sm  mb-3\"<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"input-group-text\"<\/span>&gt;<\/span>Discount\noffered<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"input-group-text\"<\/span>&gt;<\/span>%<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"number\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-control\"<\/span>\n<span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"form-discount-offered\"<\/span> <span class=\"hljs-attr\">aria-label<\/span>=<span class=\"hljs-string\">\"Discount(with percentage)\"<\/span>\n<span class=\"hljs-attr\">required<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"input-group input-group-sm  mb-3\"<\/span>&gt;<\/span>\n                       <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"input-group-text\"<\/span>&gt;<\/span>Weights<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n                       <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"input-group-text\"<\/span>&gt;<\/span>gms<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n                       <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"number\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-control\"<\/span>\n<span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"form-weights-gms\"<\/span> <span class=\"hljs-attr\">aria-label<\/span>=<span class=\"hljs-string\">\"Weights(in grams)\"<\/span> <span class=\"hljs-attr\">required<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"submit\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"btn btn-\nsuccess\"<\/span>&gt;<\/span>Predict<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">label<\/span> <span class=\"hljs-attr\">for<\/span>=<span class=\"hljs-string\">\"disabledTextInput\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-label\nprediction-label\"<\/span>&gt;<\/span>Reached on time prediction:<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">label<\/span>&gt;<\/span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"text\"<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"disabledTextInput\"<\/span>\n<span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"form-control\"<\/span> <span class=\"hljs-attr\">placeholder<\/span>=<span class=\"hljs-string\">\"No prediction\"<\/span> <span class=\"hljs-attr\">disabled<\/span>&gt;<\/span>\n                        {% if prediction == 1%}\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span>&gt;<\/span><span class=\"hljs-undefined\">\n\ndocument.getElementById('disabledTextInput').placeholder = 'Not on time'\n                        <\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n                        {% elif prediction == 0%}\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span>&gt;<\/span><span class=\"hljs-undefined\">\n\ndocument.getElementById('disabledTextInput').placeholder = 'On time'\n                        <\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n                        {% endif %}\n                    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n                  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">form<\/span>&gt;<\/span>\n           <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n     <span class=\"hljs-comment\">&lt;!-- Importing Bootstrap JS Bundle with Popper --&gt;<\/span>\n     <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span>\n<span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/cdn.jsdelivr.net\/npm\/bootstrap@5.0.2\/dist\/js\/bootstrap.bundle\n.min.js\"<\/span> <span class=\"hljs-attr\">integrity<\/span>=<span class=\"hljs-string\">\"sha384-\nMrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn\/tWtIaxVXM\"<\/span>\n<span class=\"hljs-attr\">crossorigin<\/span>=<span class=\"hljs-string\">\"anonymous\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">html<\/span>&gt;<\/span><\/span><\/pre>\n<p id=\"4b15\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">The CSS stylesheet style.css, in addition to the already functioning bootstrap CSS, helps set alignments of components using flexbox and grid, as well as font attributes and image sizing, which contain the following:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"65ea\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\"><span class=\"hljs-selector-pseudo\">:root<\/span> {\n <span class=\"hljs-attr\">--pd<\/span>: <span class=\"hljs-number\">20px<\/span>  <span class=\"hljs-comment\">\/*  padding variable *\/<\/span>\n}\n\n* {\n    <span class=\"hljs-attribute\">box-sizing<\/span>: border-box;\n    <span class=\"hljs-attribute\">margin<\/span>: <span class=\"hljs-number\">0<\/span>;\n    <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">0<\/span>;\n  }\n\n<span class=\"hljs-selector-tag\">body<\/span> {\n    <span class=\"hljs-attribute\">color<\/span>: <span class=\"hljs-number\">#131415<\/span>;\n    <span class=\"hljs-attribute\">font-family<\/span>: spezia, sans-serif;\n    <span class=\"hljs-attribute\">display<\/span>: flex;\n    <span class=\"hljs-attribute\">flex-direction<\/span>: column;\n    <span class=\"hljs-attribute\">justify-content<\/span>: space-around;\n    <span class=\"hljs-attribute\">height<\/span>: <span class=\"hljs-number\">100vh<\/span>;\n  }\n\n<span class=\"hljs-selector-class\">.about-app<\/span> <span class=\"hljs-selector-tag\">h1<\/span> {\n  <span class=\"hljs-attribute\">font-size<\/span>: <span class=\"hljs-number\">20px<\/span>;\n  <span class=\"hljs-attribute\">font-weight<\/span>: bold;\n  <span class=\"hljs-attribute\">padding-bottom<\/span>: <span class=\"hljs-built_in\">var<\/span>(--pd);\n}\n<span class=\"hljs-selector-class\">.portal<\/span> {\n  <span class=\"hljs-attribute\">display<\/span>: grid;\n  <span class=\"hljs-attribute\">grid-template-columns<\/span>: <span class=\"hljs-number\">1<\/span>fr <span class=\"hljs-number\">1<\/span>fr;\n  <span class=\"hljs-attribute\">gap<\/span>: <span class=\"hljs-number\">4em<\/span> <span class=\"hljs-number\">0.75em<\/span>;\n}\n\n<span class=\"hljs-selector-class\">.image<\/span> {\n  <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">95%<\/span>;\n  <span class=\"hljs-attribute\">border-radius<\/span>: <span class=\"hljs-number\">1%<\/span>;\n  <span class=\"hljs-attribute\">height<\/span>: auto;\n}\n<span class=\"hljs-selector-class\">.form-header<\/span> {\n  <span class=\"hljs-attribute\">font-size<\/span>: <span class=\"hljs-number\">15px<\/span>;\n  <span class=\"hljs-attribute\">font-weight<\/span>: bold;\n  <span class=\"hljs-attribute\">padding-bottom<\/span>: <span class=\"hljs-built_in\">var<\/span>(--pd);\n}\n\n<span class=\"hljs-selector-class\">.prediction-label<\/span> {\n  <span class=\"hljs-attribute\">padding-top<\/span>: <span class=\"hljs-built_in\">var<\/span>(--pd);\n  <span class=\"hljs-attribute\">font-weight<\/span>: bold;\n}<\/span><\/pre>\n<p id=\"2838\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">With that, our web application page should look like the image below:<\/p>\n<figure class=\"oz pa pb pc pd lm ls lt paragraph-image\">\n<div class=\"mc md ee me bg mf\" tabindex=\"0\" role=\"button\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg kt mg c alignnone\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:700\/1*6oLYtn8LHV4qG7UikAGDIw.png\" alt=\"e-commerce shipping web app screenshot\" width=\"700\" height=\"430\"><\/figure><div class=\"ls lt qf\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*6oLYtn8LHV4qG7UikAGDIw.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*6oLYtn8LHV4qG7UikAGDIw.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*6oLYtn8LHV4qG7UikAGDIw.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*6oLYtn8LHV4qG7UikAGDIw.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*6oLYtn8LHV4qG7UikAGDIw.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*6oLYtn8LHV4qG7UikAGDIw.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*6oLYtn8LHV4qG7UikAGDIw.png 1400w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*6oLYtn8LHV4qG7UikAGDIw.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*6oLYtn8LHV4qG7UikAGDIw.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*6oLYtn8LHV4qG7UikAGDIw.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*6oLYtn8LHV4qG7UikAGDIw.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*6oLYtn8LHV4qG7UikAGDIw.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*6oLYtn8LHV4qG7UikAGDIw.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*6oLYtn8LHV4qG7UikAGDIw.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\" data-testid=\"og\"><\/picture><\/div>\n<\/div>\n<\/figure>\n<p id=\"bfb9\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\"><strong class=\"mp fs\"><em class=\"ow\">Note: The image on the web app is the container.jpg photo found in the static folder. The image is sourced for free images on Pexels <\/em><\/strong><a class=\"af mm\" href=\"https:\/\/www.pexels.com\/photo\/cargo-containers-trailer-lot-1624695\/\" target=\"_blank\" rel=\"noopener ugc nofollow\"><strong class=\"mp fs\"><em class=\"ow\">here<\/em><\/strong><\/a><strong class=\"mp fs\"><em class=\"ow\">.<\/em><\/strong><\/p>\n<p id=\"29ea\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Our web application looks good but isn\u2019t functional; we need to capture the responses from the form, create a data frame instance, and make predictions using our model pipeline. Note that the respective form components have associated name attributes; we will request values from the form components using these attributes. To do this, we return to our flask app script app.py and create a second route named predict (directly below the end of the first route statement). We will utilize flask requests to get form responses from the index.html file. Our form applies bootstrap validation, so all inputs are required types, and all inputs are filled before predicting to avoid missing values in our data frame instance. Also, the<br>\nurl_for aids in referencing the relative path of the static files. Let\u2019s add the predict route in our app.py as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"a0e4\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\"><span class=\"hljs-comment\"># Prediction route<\/span>\n<span class=\"hljs-meta\">@app.route(<span class=\"hljs-params\"><span class=\"hljs-string\">\"\/predict\"<\/span>,  methods=[<span class=\"hljs-string\">'POST'<\/span>]<\/span>)<\/span>\n<span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title.function\">predict<\/span>():\n    <span class=\"hljs-comment\"># Extract the form values:     id = request.form['form-id']<\/span>\n    warehouse_block = request.form[<span class=\"hljs-string\">\"form-warehouse-block\"<\/span>]\n    mode_of_shipment = request.form[<span class=\"hljs-string\">\"form-shipment-mode\"<\/span>]\n    customer_care_calls = request.form[<span class=\"hljs-string\">\"form-customer-care-calls\"<\/span>]\n    customer_ratings = request.form[<span class=\"hljs-string\">\"form-customer-ratings\"<\/span>]\n    cost_of_product = request.form[<span class=\"hljs-string\">\"form_product_cost\"<\/span>]\n    prior_purchases = request.form[<span class=\"hljs-string\">\"form-prior-purchases\"<\/span>]\n    product_importance = request.form[<span class=\"hljs-string\">\"form_product_importance\"<\/span>]\n    gender = request.form[<span class=\"hljs-string\">\"form-gender\"<\/span>]\n    discount_offered = request.form[<span class=\"hljs-string\">\"form-discount-offered\"<\/span>]\n    weights_gms = request.form[<span class=\"hljs-string\">\"form-weights-gms\"<\/span>]\n    form_data = {\n        <span class=\"hljs-string\">\"ID\"<\/span>: [<span class=\"hljs-built_in\">id<\/span>],\n        <span class=\"hljs-string\">\"Warehouse_block\"<\/span>: [warehouse_block],\n        <span class=\"hljs-string\">\"Mode_of_Shipment\"<\/span>: [mode_of_shipment],\n        <span class=\"hljs-string\">\"Customer_care_calls\"<\/span>: [customer_care_calls],\n        <span class=\"hljs-string\">\"Customer_rating\"<\/span>: [customer_ratings],\n        <span class=\"hljs-string\">\"Cost_of_the_Product\"<\/span>: [cost_of_product],\n        <span class=\"hljs-string\">\"Prior_purchases\"<\/span>: [prior_purchases],\n        <span class=\"hljs-string\">\"Product_importance\"<\/span>: [product_importance],\n        <span class=\"hljs-string\">\"Gender\"<\/span>: [gender],\n        <span class=\"hljs-string\">\"Discount_offered\"<\/span>: [discount_offered],\n        <span class=\"hljs-string\">\"Weight_in_gms\"<\/span>: [weights_gms]\n    }\n    <span class=\"hljs-comment\"># create form dataframe to apply model pipeline     <\/span>\n    form_df = pd.DataFrame(form_data)\n    form_df.drop(columns=[<span class=\"hljs-string\">'ID'<\/span>], inplace=<span class=\"hljs-literal\">True<\/span>)\n\n    <span class=\"hljs-comment\"># loading model pipeline<\/span>\n    model_pipeline = pickle.load(<span class=\"hljs-built_in\">open<\/span>(<span class=\"hljs-string\">\"pipeline.pkl\"<\/span>, <span class=\"hljs-string\">\"rb\"<\/span>))\n    <span class=\"hljs-comment\"># applying model pipeline from form dataframe to make predictions     <\/span>\n    my_prediction = model_pipeline.predict(form_df)\n    <span class=\"hljs-keyword\">return<\/span> render_template(<span class=\"hljs-string\">'index.html'<\/span>, prediction=my_prediction)<\/span><\/pre>\n<p id=\"025a\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">The prediction is sent to index.html using the Jinja template (i.e., the {} conditional statement in the prediction section of the index.html). Our Flask app is ready, and we can test it application by typing the following on your terminal:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"4bd8\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">python3 app.<span class=\"hljs-property\">py<\/span><\/span><\/pre>\n<p id=\"689a\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">or<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"ede6\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">flask run<\/span><\/pre>\n<p id=\"bc84\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Both run the application locally. You will see output like the following, including a helpful warning reminding you not to use this server setup in production:<\/p>\n<figure class=\"oz pa pb pc pd lm ls lt paragraph-image\">\n<div class=\"mc md ee me bg mf\" tabindex=\"0\" role=\"button\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg kt mg c alignnone\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:638\/1*Wm9f6wrOcGMKjAtX96IRPw.png\" alt=\"code output\" width=\"638\" height=\"174\"><\/figure><div class=\"ls lt qg\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*Wm9f6wrOcGMKjAtX96IRPw.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*Wm9f6wrOcGMKjAtX96IRPw.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*Wm9f6wrOcGMKjAtX96IRPw.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*Wm9f6wrOcGMKjAtX96IRPw.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*Wm9f6wrOcGMKjAtX96IRPw.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*Wm9f6wrOcGMKjAtX96IRPw.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1276\/format:webp\/1*Wm9f6wrOcGMKjAtX96IRPw.png 1276w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 638px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*Wm9f6wrOcGMKjAtX96IRPw.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*Wm9f6wrOcGMKjAtX96IRPw.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*Wm9f6wrOcGMKjAtX96IRPw.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*Wm9f6wrOcGMKjAtX96IRPw.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*Wm9f6wrOcGMKjAtX96IRPw.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*Wm9f6wrOcGMKjAtX96IRPw.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1276\/1*Wm9f6wrOcGMKjAtX96IRPw.png 1276w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 638px\" data-testid=\"og\"><\/picture><\/div>\n<\/div>\n<\/figure>\n<p id=\"8425\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">The app is currently running on my IP address. On your system, visit your server&#8217;s IP address followed by the port:5000 in your web browser, like <a class=\"af mm\" href=\"http:\/\/your_server_ip:5000\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">http:\/\/your_server_ip:5000<\/a>, to load and view our flask application. A quick demo of our app working is shown below:<\/p>\n<figure class=\"oz pa pb pc pd lm ls lt paragraph-image\">\n<div class=\"mc md ee me bg mf\" tabindex=\"0\" role=\"button\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg kt mg c alignnone\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:700\/1*ok3ze7LNbLWEYwJko76NNQ.png\" alt=\"e-commerce shipping web app screenshot\" width=\"700\" height=\"354\"><\/figure><div class=\"ls lt qh\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*ok3ze7LNbLWEYwJko76NNQ.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*ok3ze7LNbLWEYwJko76NNQ.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*ok3ze7LNbLWEYwJko76NNQ.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*ok3ze7LNbLWEYwJko76NNQ.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*ok3ze7LNbLWEYwJko76NNQ.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*ok3ze7LNbLWEYwJko76NNQ.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*ok3ze7LNbLWEYwJko76NNQ.png 1400w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*ok3ze7LNbLWEYwJko76NNQ.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*ok3ze7LNbLWEYwJko76NNQ.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*ok3ze7LNbLWEYwJko76NNQ.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*ok3ze7LNbLWEYwJko76NNQ.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*ok3ze7LNbLWEYwJko76NNQ.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*ok3ze7LNbLWEYwJko76NNQ.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*ok3ze7LNbLWEYwJko76NNQ.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\" data-testid=\"og\"><\/picture><\/div>\n<\/div>\n<\/figure>\n<p id=\"9607\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">The Flask development server (Werkzeug\u2019s Web Server Gateway Interface (WSGI) server) is unsuitable for production as it can only handle one request at a time. Also, its performance and security aren&#8217;t efficient and stable. Notice that if we terminate the Flask app on our terminal, our application will no longer be reachable. We must switch from this Flask\u2019s development server to a production WSGI server. Many WSGI servers have different configurations, such as <a class=\"af mm\" href=\"https:\/\/gunicorn.org\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">gunicorn<\/a>, <a class=\"af mm\" href=\"https:\/\/docs.pylonsproject.org\/projects\/waitress\/en\/latest\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">waitress<\/a>, <a class=\"af mm\" href=\"https:\/\/github.com\/jonashaag\/bjoern\" target=\"_blank\" rel=\"noopener ugc nofollow\">bjoern<\/a>, <a class=\"af mm\" href=\"https:\/\/modwsgi.readthedocs.io\/en\/master\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">mod_wsgi<\/a>, and <a class=\"af mm\" href=\"https:\/\/www.gevent.org\/api\/gevent.pywsgi.html\" target=\"_blank\" rel=\"noopener ugc nofollow\">gevent<\/a>. Based on its simplicity, popularity, and speed, I will switch from the Flask development server to the Gunicorn. For this switch, we will create a new wsgi.py file, where we will import our flask application and run it as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"5c9c\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\"><span class=\"hljs-comment\"># importing flask app <\/span>\n<span class=\"hljs-keyword\">from<\/span> app <span class=\"hljs-keyword\">import<\/span> app\n\n<span class=\"hljs-keyword\">if<\/span> __name__ == <span class=\"hljs-string\">\"__main__\"<\/span>:\n    app.run()<\/span><\/pre>\n<p id=\"6411\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">To start serving our application with Gunicorn, we execute the following on our terminal as we access our Flask app from the wsgi.py script and bind it to port 5000 as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"6b94\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">gunicorn --<span class=\"hljs-built_in\">bind<\/span> 0.0.0.0:5000 wsgi:app<\/span><\/pre>\n<p id=\"6054\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">The output should look like this:<\/p>\n<figure class=\"oz pa pb pc pd lm ls lt paragraph-image\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg kt mg c alignnone\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:638\/1*YMWbmGT-fFk04YmUMSX-kw.png\" alt=\"code output\" width=\"638\" height=\"81\"><\/figure><div class=\"ls lt qg\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*YMWbmGT-fFk04YmUMSX-kw.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*YMWbmGT-fFk04YmUMSX-kw.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*YMWbmGT-fFk04YmUMSX-kw.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*YMWbmGT-fFk04YmUMSX-kw.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*YMWbmGT-fFk04YmUMSX-kw.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*YMWbmGT-fFk04YmUMSX-kw.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1276\/format:webp\/1*YMWbmGT-fFk04YmUMSX-kw.png 1276w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 638px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*YMWbmGT-fFk04YmUMSX-kw.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*YMWbmGT-fFk04YmUMSX-kw.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*YMWbmGT-fFk04YmUMSX-kw.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*YMWbmGT-fFk04YmUMSX-kw.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*YMWbmGT-fFk04YmUMSX-kw.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*YMWbmGT-fFk04YmUMSX-kw.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1276\/1*YMWbmGT-fFk04YmUMSX-kw.png 1276w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 638px\" data-testid=\"og\"><\/picture><\/div>\n<\/figure>\n<p id=\"e661\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">The above command runs the server in the foreground; when we terminate the application via our terminal, our application will no longer be reachable. We can run the server in the background, where closing the application runtime on the terminal won\u02bct affect the application&#8217;s reachability. It can be stopped by killing it on the process\/task manager as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"0049\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">gunicorn --<span class=\"hljs-built_in\">bind<\/span> 0.0.0.0:5000 wsgi:app  &amp;<\/span><\/pre>\n<p id=\"ddef\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">We can access our app via both channels (foreground and background) at <a class=\"af mm\" href=\"http:\/\/0.0.0.0:5000\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">http:\/\/0.0.0.0:5000<\/a>, which means listening to port 5000 on all IPs as 0.0.0.0 is a placeholder.<\/p>\n<p id=\"2a6f\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Lastly, let\u2019s record all our virtual environment current package list into a text file requirements.txt at the app directory by running the following on our terminal:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"be48\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">pip3 freeze &gt; requirements.<span class=\"hljs-property\">txt<\/span><\/span><\/pre>\n<h2 id=\"4008\" class=\"nl nm fr be nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh oi bj\">Containerization of the Application Using Docker<\/h2>\n<p id=\"1b4b\" class=\"pw-post-body-paragraph mn mo fr mp b mq oj ms mt mu ok mw mx my ol na nb nc om ne nf ng on ni nj nk fk bj\" data-selectable-paragraph=\"\">With our application built and functional, we will move next to containerize our application using Docker. First, we start our Docker desktop (for Mac and Windows users), so the docker daemon can run by simply opening the installed Docker desktop app on your local machine. Next, create a Dockerfile in the app directory of our project by creating a file, naming it Dockerfile with no extension, and adding the following snippet in that file:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"fd4b\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\"><span class=\"hljs-comment\"># start by pulling the python image <\/span>\nFROM python:3.8-slim-buster\n\n<span class=\"hljs-comment\"># Set and create the working directory to \/app <\/span>\nWORKDIR \/app\n\n<span class=\"hljs-comment\"># Copy the current directory contents into \/app <\/span>\nCOPY . \/app\n\n<span class=\"hljs-comment\"># informs Docker that this container should listen to network port 5000 at <\/span>\nruntime\nEXPOSE 5000\n\n<span class=\"hljs-comment\"># install the dependencies and packages in the requirements file<\/span>\nRUN apt-get -y update\nRUN apt-get update &amp;&amp; apt-get install -y python3 python3-pip\nRUN pip3 install -r requirements.txt\n\n<span class=\"hljs-comment\">#  executing the container<\/span>\nCMD [<span class=\"hljs-string\">\"gunicorn\"<\/span>, <span class=\"hljs-string\">\"--bind\"<\/span>, <span class=\"hljs-string\">\"0.0.0.0:5000\"<\/span>, <span class=\"hljs-string\">\"wsgi:app\"<\/span>]<\/span><\/pre>\n<p id=\"193e\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Before we build a docker image using the Dockerfile for our application, let\u2019s first understand the instructions in the Dockerfile:<\/p>\n<ul class=\"\">\n<li id=\"7b93\" class=\"mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">FROM python:3.8-slim-buster: While it is possible to create base images, Docker allows us to inherit existing images. Here, we install a basic Debian Python image in our Docker image.<\/li>\n<li id=\"f42c\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">WORKDIR \/app: The WORKDIR instruction defines the default working directory of our application in the container image where subsequent Dockerfile instructions such as RUN, CMD, ENTRYPOINT, COPY, and ADD will be operated. The syntax in our Dockerfile is WORKDIR &lt;\/path\/to\/workdir&gt;, the default path \/, but it is considered good practice to specify your WORKDIR. If the WORKDIR is specified in the Docker file, like in our case\/app, it creates the directory in our container image, so we can say it implicitly performs mkdirandcd. Here, we set the working directory as \/app, which will be the root directory of our application in the container image. It is possible to have multiple WORKDIR instructions in your Dockerfile`.<\/li>\n<li id=\"14cc\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">COPY . \/app: As the name implies, it copies files or directories from the local computer to the filesystem of the image following the syntax COPY &lt;src&gt; &lt;dest&gt; where the src and dest are file paths of the directory on the local machine and destination to the directory in our docker image filesystem. Here, we are copying everything from the directory where the Dockerfile is located in our local machine to our working directory (app) that includes files and directories such as the app.py, wsgi.py, pipeline.pkl, requirements.txt, static, and templates.<\/li>\n<li id=\"f952\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">EXPOSE 5000: The EXPOSE instruction informs the image created using this Dockerfile to listen to port 5000 when running a container. This helps build and deploy network-aware container applications and aids inter-container communication. The EXPOSE instruction syntax is EXPOSE&lt;port&gt;\/&lt;protocol&gt;, where the protocol is either TCP or UDP, with TCP being the default protocol. Note that this instruction does not map ports on the local machine.<\/li>\n<li id=\"fa08\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">RUN commands: The RUN instructions are executed as a shell command within the container at build time. Here, it installs pip3 and all the dependencies defined in the requirements.txt file into our application within the container.<br>\nCMD [\u201cgunicorn\u201d, \u201c \u2014 bind\u201d, \u201c0.0.0.0:5000\u201d,wsgi:app\u201d]: This CMD command instructs Docker to run our flask app in the Gunicorn server as a module and also makes the container available externally with the host 0.0.0.0 and binding it to port 5000.<\/li>\n<\/ul>\n<p id=\"56f5\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Next, let&#8217;s proceed to build our Docker image using the tag (mutable reference name) shipping_app from this Dockerfile as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"c020\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">docker build -t shipping_app .<\/span><\/pre>\n<p id=\"5b97\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">With the image successfully built, the output should look similar to the following:<\/p>\n<figure class=\"oz pa pb pc pd lm ls lt paragraph-image\">\n<div class=\"mc md ee me bg mf\" tabindex=\"0\" role=\"button\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg kt mg c alignnone\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:700\/1*cAYyErVrsKe7dAdBkwR4eQ.png\" alt=\"code output\" width=\"700\" height=\"331\"><\/figure><div class=\"ls lt qi\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*cAYyErVrsKe7dAdBkwR4eQ.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*cAYyErVrsKe7dAdBkwR4eQ.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*cAYyErVrsKe7dAdBkwR4eQ.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*cAYyErVrsKe7dAdBkwR4eQ.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*cAYyErVrsKe7dAdBkwR4eQ.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*cAYyErVrsKe7dAdBkwR4eQ.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*cAYyErVrsKe7dAdBkwR4eQ.png 1400w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*cAYyErVrsKe7dAdBkwR4eQ.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*cAYyErVrsKe7dAdBkwR4eQ.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*cAYyErVrsKe7dAdBkwR4eQ.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*cAYyErVrsKe7dAdBkwR4eQ.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*cAYyErVrsKe7dAdBkwR4eQ.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*cAYyErVrsKe7dAdBkwR4eQ.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*cAYyErVrsKe7dAdBkwR4eQ.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\" data-testid=\"og\"><\/picture><\/div>\n<\/div>\n<\/figure>\n<p id=\"5f86\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">We can view the built images from the Docker desktop application or on our terminal (command line) as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"ec4d\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">docker images<\/span><\/pre>\n<p id=\"6b70\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Next, we run an instance of the image (container) as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"d297\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">docker run -<span class=\"hljs-attr\">p5000<\/span>:<span class=\"hljs-number\">5000<\/span>  shipping_app<\/span><\/pre>\n<p id=\"e3c9\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">This command runs the containerized application, binding the port allocated to the container on our machine to the port where the application will run on the container. This yields the following:<\/p>\n<figure class=\"oz pa pb pc pd lm ls lt paragraph-image\">\n<div class=\"mc md ee me bg mf\" tabindex=\"0\" role=\"button\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg kt mg c alignnone\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:700\/1*oVKvLn7qge2uKp26ga0xng.png\" alt=\"code screenshot\" width=\"700\" height=\"77\"><\/figure><div class=\"ls lt qi\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*oVKvLn7qge2uKp26ga0xng.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*oVKvLn7qge2uKp26ga0xng.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*oVKvLn7qge2uKp26ga0xng.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*oVKvLn7qge2uKp26ga0xng.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*oVKvLn7qge2uKp26ga0xng.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*oVKvLn7qge2uKp26ga0xng.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*oVKvLn7qge2uKp26ga0xng.png 1400w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*oVKvLn7qge2uKp26ga0xng.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*oVKvLn7qge2uKp26ga0xng.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*oVKvLn7qge2uKp26ga0xng.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*oVKvLn7qge2uKp26ga0xng.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*oVKvLn7qge2uKp26ga0xng.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*oVKvLn7qge2uKp26ga0xng.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*oVKvLn7qge2uKp26ga0xng.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\" data-testid=\"og\"><\/picture><\/div>\n<\/div>\n<\/figure>\n<p id=\"cb8e\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Where the application can be accessed at <a class=\"af mm\" href=\"http:\/\/yourip:5000\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">http:\/\/yourip:5000<\/a><\/p>\n<p id=\"d343\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">However, it is best to run the container in detached mode by the option \u2014 detach or -d, where the container runs at terminal background, where terminating the application runtime on the terminal won\u02bct affect the application reachability. We make the following modification to our docker run command as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"3a22\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">docker run -d -<span class=\"hljs-selector-tag\">p<\/span> <span class=\"hljs-number\">5000<\/span>:<span class=\"hljs-number\">5000<\/span> shipping_app<\/span><\/pre>\n<p id=\"6545\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">We can see the containers currently running using the following commands:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"5ea3\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">docker ps<\/span><\/pre>\n<p id=\"affc\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">The output is as follows:<\/p>\n<figure class=\"oz pa pb pc pd lm ls lt paragraph-image\">\n<div class=\"mc md ee me bg mf\" tabindex=\"0\" role=\"button\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg kt mg c alignnone\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:700\/1*jBPfyaODz54BuCyIL_ELig.png\" alt=\"code screenshot\" width=\"700\" height=\"35\"><\/figure><div class=\"ls lt qj\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*jBPfyaODz54BuCyIL_ELig.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*jBPfyaODz54BuCyIL_ELig.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*jBPfyaODz54BuCyIL_ELig.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*jBPfyaODz54BuCyIL_ELig.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*jBPfyaODz54BuCyIL_ELig.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*jBPfyaODz54BuCyIL_ELig.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*jBPfyaODz54BuCyIL_ELig.png 1400w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*jBPfyaODz54BuCyIL_ELig.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*jBPfyaODz54BuCyIL_ELig.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*jBPfyaODz54BuCyIL_ELig.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*jBPfyaODz54BuCyIL_ELig.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*jBPfyaODz54BuCyIL_ELig.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*jBPfyaODz54BuCyIL_ELig.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*jBPfyaODz54BuCyIL_ELig.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\" data-testid=\"og\"><\/picture><\/div>\n<\/div>\n<\/figure>\n<p id=\"1f00\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">The previous command shows us the active container (which is the one we ran on detached mode). To view all containers, including the ones that aren\u02bct running, we use the following commands:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"e7a8\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">docker ps -<span class=\"hljs-selector-tag\">a<\/span><\/span><\/pre>\n<figure class=\"oz pa pb pc pd lm ls lt paragraph-image\">\n<div class=\"mc md ee me bg mf\" tabindex=\"0\" role=\"button\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg kt mg c alignnone\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:700\/1*n73pRgyluZGEBiO9zKyhjA.png\" alt=\"code screenshot\" width=\"700\" height=\"46\"><\/figure><div class=\"ls lt qk\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*n73pRgyluZGEBiO9zKyhjA.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*n73pRgyluZGEBiO9zKyhjA.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*n73pRgyluZGEBiO9zKyhjA.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*n73pRgyluZGEBiO9zKyhjA.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*n73pRgyluZGEBiO9zKyhjA.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*n73pRgyluZGEBiO9zKyhjA.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*n73pRgyluZGEBiO9zKyhjA.png 1400w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*n73pRgyluZGEBiO9zKyhjA.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*n73pRgyluZGEBiO9zKyhjA.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*n73pRgyluZGEBiO9zKyhjA.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*n73pRgyluZGEBiO9zKyhjA.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*n73pRgyluZGEBiO9zKyhjA.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*n73pRgyluZGEBiO9zKyhjA.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*n73pRgyluZGEBiO9zKyhjA.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\" data-testid=\"og\"><\/picture><\/div>\n<\/div>\n<\/figure>\n<h2 id=\"fe9d\" class=\"nl nm fr be nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh oi bj\">Deploying Our Flask Application to Docker Hub<\/h2>\n<p id=\"6b07\" class=\"pw-post-body-paragraph mn mo fr mp b mq oj ms mt mu ok mw mx my ol na nb nc om ne nf ng on ni nj nk fk bj\" data-selectable-paragraph=\"\"><a class=\"af mm\" href=\"https:\/\/hub.docker.com\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">DockerHub<\/a> is a service provided by Docker that serves as a community of repositories where Docker users create, test, manage, store, and share container images. It is free for public repositories and has a <a class=\"af mm\" href=\"https:\/\/www.docker.com\/pricing\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">subscription plan<\/a> for private repositories. In this section, we will push (upload) our container image to DockerHub so you can access it anywhere.<\/p>\n<p id=\"8f7d\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Follow the following steps:<\/p>\n<ul class=\"\">\n<li id=\"3c4f\" class=\"mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk ox op oq bj\" data-selectable-paragraph=\"\"><a class=\"af mm\" href=\"https:\/\/hub.docker.com\/signup\" target=\"_blank\" rel=\"noopener ugc nofollow\">Sign up on Docker Hub<\/a> if you don\u2019t already have an account.<\/li>\n<li id=\"2a5d\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">After creating an account and successfully logging in, click on the Repositories navigation bar and create a new repository as follows:<\/li>\n<\/ul>\n<figure class=\"oz pa pb pc pd lm ls lt paragraph-image\">\n<div class=\"mc md ee me bg mf\" tabindex=\"0\" role=\"button\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg kt mg c alignnone\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:700\/1*3abERyVEYrlGVX_t9zJMzQ.png\" alt=\"screenshot of how to create a Docker Hub repository\" width=\"700\" height=\"305\"><\/figure><div class=\"ls lt ql\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*3abERyVEYrlGVX_t9zJMzQ.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*3abERyVEYrlGVX_t9zJMzQ.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*3abERyVEYrlGVX_t9zJMzQ.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*3abERyVEYrlGVX_t9zJMzQ.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*3abERyVEYrlGVX_t9zJMzQ.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*3abERyVEYrlGVX_t9zJMzQ.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*3abERyVEYrlGVX_t9zJMzQ.png 1400w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*3abERyVEYrlGVX_t9zJMzQ.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*3abERyVEYrlGVX_t9zJMzQ.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*3abERyVEYrlGVX_t9zJMzQ.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*3abERyVEYrlGVX_t9zJMzQ.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*3abERyVEYrlGVX_t9zJMzQ.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*3abERyVEYrlGVX_t9zJMzQ.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*3abERyVEYrlGVX_t9zJMzQ.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\" data-testid=\"og\"><\/picture><\/div>\n<\/div>\n<\/figure>\n<ul class=\"\">\n<li id=\"5805\" class=\"mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Click Create, which will successfully create your first Docker Hub repository. You should see:<\/li>\n<\/ul>\n<figure class=\"oz pa pb pc pd lm ls lt paragraph-image\">\n<div class=\"mc md ee me bg mf\" tabindex=\"0\" role=\"button\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg kt mg c alignnone\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:700\/1*ZQer9wMDWGuuzFcTrxfKsQ.png\" alt=\"create Docker Hub repository\" width=\"700\" height=\"490\"><\/figure><div class=\"ls lt ql\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*ZQer9wMDWGuuzFcTrxfKsQ.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*ZQer9wMDWGuuzFcTrxfKsQ.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*ZQer9wMDWGuuzFcTrxfKsQ.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*ZQer9wMDWGuuzFcTrxfKsQ.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*ZQer9wMDWGuuzFcTrxfKsQ.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*ZQer9wMDWGuuzFcTrxfKsQ.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*ZQer9wMDWGuuzFcTrxfKsQ.png 1400w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*ZQer9wMDWGuuzFcTrxfKsQ.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*ZQer9wMDWGuuzFcTrxfKsQ.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*ZQer9wMDWGuuzFcTrxfKsQ.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*ZQer9wMDWGuuzFcTrxfKsQ.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*ZQer9wMDWGuuzFcTrxfKsQ.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*ZQer9wMDWGuuzFcTrxfKsQ.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*ZQer9wMDWGuuzFcTrxfKsQ.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\" data-testid=\"og\"><\/picture><\/div>\n<\/div>\n<\/figure>\n<ul class=\"\">\n<li id=\"7dec\" class=\"mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Next, with our Docker Hub repository set up, we need to connect Docker Hub and our local machine. On our terminal in our local machine, log into Docker, which will prompt you to enter your Docker Hub username and password as follows:<\/li>\n<\/ul>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"0ce8\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">docker login<\/span><\/pre>\n<ul class=\"\">\n<li id=\"68f6\" class=\"mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Upon successful login, before we push our image to the created repository, we have to rename our image to the standard format following &lt;your-docker-hub-username&gt;\/&lt;repository-name&gt;. We renamed our Docker image as follows:<\/li>\n<\/ul>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"6595\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">docker tag shipping_app  &lt;your-docker-hub-username&gt;\/shipping_app<\/span><\/pre>\n<ul class=\"\">\n<li id=\"0ee8\" class=\"mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Lastly, we push the image to Docker Hub as follows:<\/li>\n<\/ul>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"08a4\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">docker push &lt;your-docker-hub-username&gt;\/shipping_app<\/span><\/pre>\n<p id=\"3c16\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Once completed, your Docker Hub repository should look like this:<\/p>\n<figure class=\"oz pa pb pc pd lm ls lt paragraph-image\">\n<div class=\"mc md ee me bg mf\" tabindex=\"0\" role=\"button\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg kt mg c alignnone\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:700\/1*5zpAUtLxb8FSk-GZ9Voxmw.png\" alt=\"screenshot of Docker Hub repository\" width=\"700\" height=\"490\"><\/figure><div class=\"ls lt ql\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*5zpAUtLxb8FSk-GZ9Voxmw.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*5zpAUtLxb8FSk-GZ9Voxmw.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*5zpAUtLxb8FSk-GZ9Voxmw.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*5zpAUtLxb8FSk-GZ9Voxmw.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*5zpAUtLxb8FSk-GZ9Voxmw.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*5zpAUtLxb8FSk-GZ9Voxmw.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*5zpAUtLxb8FSk-GZ9Voxmw.png 1400w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*5zpAUtLxb8FSk-GZ9Voxmw.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*5zpAUtLxb8FSk-GZ9Voxmw.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*5zpAUtLxb8FSk-GZ9Voxmw.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*5zpAUtLxb8FSk-GZ9Voxmw.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*5zpAUtLxb8FSk-GZ9Voxmw.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*5zpAUtLxb8FSk-GZ9Voxmw.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*5zpAUtLxb8FSk-GZ9Voxmw.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\" data-testid=\"og\"><\/picture><\/div>\n<\/div>\n<\/figure>\n<p id=\"3f77\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">To pull this image from Docker Hub, we need to use the docker pull command using the syntax docker pull &lt;your-docker-hub-username&gt;\/&lt;repository-name&gt;:tagname as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"b75f\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">docker pull codebrain001\/shipping_app<\/span><\/pre>\n<p id=\"6fde\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">With the image successfully pulled, you can test the application using the docker run command following the syntax docker run &lt;your-docker-hub-username&gt;\/&lt;repository-name&gt;:tagname as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"b5d9\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">docker run codebrain001\/shipping_app<\/span><\/pre>\n<p id=\"aeb7\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\"><em class=\"ow\">If you don\u2019t have Docker installed on your machine and want to test the application, you can use <\/em><a href=\"https:\/\/labs.play-with-docker.com\/\"><em class=\"ow\">Play with Docker<\/em><\/a><em class=\"ow\">, creating a virtual machine browser where we can build and run Docker containers.<\/em><\/p>\n<h2 id=\"126e\" class=\"nl nm fr be nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh oi bj\">Deploying the Containerization Application to the Cloud<\/h2>\n<p id=\"37c6\" class=\"pw-post-body-paragraph mn mo fr mp b mq oj ms mt mu ok mw mx my ol na nb nc om ne nf ng on ni nj nk fk bj\" data-selectable-paragraph=\"\">Next, we will host our containerized application on the cloud to leverage cloud infrastructure rather than on-premise. This cloud infrastructure will also enable our hosted applications to be accessed and interacted with over the internet. Platform as a service (PaaS) provides a complete cloud environment, flexible and scalable, to develop, deploy, run, manage, and host applications. Numerous platforms can host our Python containerized application, such as <a href=\"https:\/\/aws.amazon.com\/elasticbeanstalk\/\">Heroku<\/a>, <a href=\"https:\/\/www.pythonanywhere.com\/\">PythonAnywhere<\/a>, <a href=\"https:\/\/platform.sh\/\">Platform.sh<\/a>, <a href=\"https:\/\/cloud.google.com\/appengine\">Google App Engine<\/a>, <a href=\"https:\/\/www.digitalocean.com\/\">Digitalocean app platform<\/a>, and <a href=\"https:\/\/aws.amazon.com\/elasticbeanstalk\/\">AWS Elastic Beanstalk<\/a>. With Docker enabling containerization of our app, we can move our application to any cloud provider. For this tutorial, we will use Heroku due to its simplicity of deployment and popularity.<\/p>\n<p id=\"6667\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Heroku makes developing and deploying Python applications (built with Flask or Django) easy. Heroku handles infrastructure details such as providing HTTPS certificates, managing DNS records, and running and maintaining servers. Let\u2019s start deploying our containerized application to Heroku using its <a href=\"https:\/\/devcenter.heroku.com\/articles\/container-registry-and-runtime\">Container Registry<\/a>.<\/p>\n<ul class=\"\">\n<li id=\"63ae\" class=\"mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">First, <a href=\"https:\/\/signup.heroku.com\/\">sign up on Heroku<\/a> if you don\u2019t already have an account.<\/li>\n<li id=\"372a\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Next, <a href=\"https:\/\/devcenter.heroku.com\/articles\/heroku-cli\">install the Heroku CLI<\/a>, which helps us create and manage our Heroku apps from the terminal. It is the convenient and quickest way to deploy our application.<\/li>\n<li id=\"99c6\" class=\"mn mo fr mp b mq or ms mt mu os mw mx my ot na nb nc ou ne nf ng ov ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">With the Heroku CLI installed, let\u2019s connect our Heroku account to our local machine by login on our terminal as follows:<\/li>\n<\/ul>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"644e\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">heroku login<\/span><\/pre>\n<ul class=\"\">\n<li id=\"77b4\" class=\"mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">We can use the Heroku CLI to build and manage our application upon successful login. Next, we create a Procfile with no extension in the name, still located in our application directory. This <a href=\"https:\/\/devcenter.heroku.com\/articles\/procfile\">Procfile<\/a> detail commands that the Heroku app on startup will execute and tells Heroku how to run the app. The content of the Procfile is as follows:<\/li>\n<\/ul>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"3eb1\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">web: gunicorn --<span class=\"hljs-built_in\">bind<\/span> 0.0.0.0:<span class=\"hljs-variable\">$PORT<\/span> wsgi:app<\/span><\/pre>\n<p id=\"9abe\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\"><em class=\"ow\">The Procfile filename must start with a capital P, and there must not be any comments inside the file<\/em><\/p>\n<ul class=\"\">\n<li id=\"5333\" class=\"mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Next, add all the files and changes to the Git repository as follows:<\/li>\n<\/ul>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"052d\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">git <span class=\"hljs-keyword\">add<\/span> .<\/span><\/pre>\n<ul class=\"\">\n<li id=\"5e28\" class=\"mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Next, add a commit message used to save the changes on Git as follows:<\/li>\n<\/ul>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"7319\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">git <span class=\"hljs-keyword\">commit<\/span> <span class=\"hljs-operator\">-<\/span>m \"Added application files ready for deployment to Heroku\"<\/span><\/pre>\n<ul class=\"\">\n<li id=\"5879\" class=\"mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Next, we create a Heroku application as follows:<\/li>\n<\/ul>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"1ae7\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">heroku <span class=\"hljs-built_in\">create<\/span> ecommerce-shipping-app<\/span><\/pre>\n<p id=\"d595\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">This command initialized our Heroku application and created a Git remote (remote repository hosted on the internet) named heroku. Heroku application names must be unique; hence, choose a different application name for your deployment. The output should be similar to this:<\/p>\n<figure class=\"oz pa pb pc pd lm ls lt paragraph-image\">\n<div class=\"mc md ee me bg mf\" tabindex=\"0\" role=\"button\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg kt mg c alignnone\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:700\/1*TjM1g3x2s_fjvTZrVqF_6g.png\" alt=\"code screenshot\" width=\"700\" height=\"43\"><\/figure><div class=\"ls lt qm\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*TjM1g3x2s_fjvTZrVqF_6g.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*TjM1g3x2s_fjvTZrVqF_6g.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*TjM1g3x2s_fjvTZrVqF_6g.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*TjM1g3x2s_fjvTZrVqF_6g.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*TjM1g3x2s_fjvTZrVqF_6g.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*TjM1g3x2s_fjvTZrVqF_6g.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*TjM1g3x2s_fjvTZrVqF_6g.png 1400w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*TjM1g3x2s_fjvTZrVqF_6g.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*TjM1g3x2s_fjvTZrVqF_6g.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*TjM1g3x2s_fjvTZrVqF_6g.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*TjM1g3x2s_fjvTZrVqF_6g.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*TjM1g3x2s_fjvTZrVqF_6g.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*TjM1g3x2s_fjvTZrVqF_6g.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*TjM1g3x2s_fjvTZrVqF_6g.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\" data-testid=\"og\"><\/picture><\/div>\n<\/div>\n<\/figure>\n<ul class=\"\">\n<li id=\"4822\" class=\"mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk ox op oq bj\" data-selectable-paragraph=\"\">Next, we need to push the Git repository to this Heroku remote to trigger the build and deployment process as follows:<\/li>\n<\/ul>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"c1a4\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">git <span class=\"hljs-keyword\">push<\/span> heroku master<\/span><\/pre>\n<p id=\"c57c\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">The output will show the building and deployment process and installation of dependencies information as the commands execute (pushing the main branch to the Heroku remote).<\/p>\n<figure class=\"oz pa pb pc pd lm ls lt paragraph-image\">\n<div class=\"mc md ee me bg mf\" tabindex=\"0\" role=\"button\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg kt mg c alignnone\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:700\/1*bsEcUTFWDmaygOiu5eEPPg.png\" alt=\"code screenshot of containerization\" width=\"700\" height=\"229\"><\/figure><div class=\"ls lt qn\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*bsEcUTFWDmaygOiu5eEPPg.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*bsEcUTFWDmaygOiu5eEPPg.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*bsEcUTFWDmaygOiu5eEPPg.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*bsEcUTFWDmaygOiu5eEPPg.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*bsEcUTFWDmaygOiu5eEPPg.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*bsEcUTFWDmaygOiu5eEPPg.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*bsEcUTFWDmaygOiu5eEPPg.png 1400w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*bsEcUTFWDmaygOiu5eEPPg.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*bsEcUTFWDmaygOiu5eEPPg.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*bsEcUTFWDmaygOiu5eEPPg.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*bsEcUTFWDmaygOiu5eEPPg.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*bsEcUTFWDmaygOiu5eEPPg.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*bsEcUTFWDmaygOiu5eEPPg.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*bsEcUTFWDmaygOiu5eEPPg.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\" data-testid=\"og\"><\/picture><\/div>\n<\/div>\n<\/figure>\n<p id=\"be7c\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Congratulations, our application is now online. You can find the URL at the output of the last execution following the syntax https:\/\/&lt;your-app-name&gt;.herokuapp.com\/. My application is at <a class=\"af mm\" href=\"https:\/\/ecommerce-shipping-app.herokuapp.com\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">https:\/\/ecommerce-shipping-app.herokuapp.com\/<\/a> (This explains why the app name has to be unique, as different applications can share the same URL).<\/p>\n<p id=\"17db\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Alternatively, you can open your application via the Heroku CLI as follows:<\/p>\n<pre class=\"oz pa pb pc pd pv pw px bo py ba bj\"><span id=\"89ec\" class=\"pz nm fr pw b bf qa qb l qc qd\" data-selectable-paragraph=\"\">heroku <span class=\"hljs-keyword\">open<\/span><\/span><\/pre>\n<h2 id=\"d10f\" class=\"nl nm fr be nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh oi bj\">Conclusion<\/h2>\n<p id=\"9dec\" class=\"pw-post-body-paragraph mn mo fr mp b mq oj ms mt mu ok mw mx my ol na nb nc om ne nf ng on ni nj nk fk bj\" data-selectable-paragraph=\"\">In this guide, we build a machine learning model (classifier) and create a flask application with a WSGI production server. Afterward, we containerized the machine learning application with Docker and shared the created Docker image with Docker Hub. Lastly, we pushed a containerized machine learning application to Heroku to access it over the internet.<\/p>\n<p id=\"7c6b\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">For more information on incorporating Docker with your application, the Docker documentation is a valuable resource you can reference.<\/p>\n<p id=\"d8c1\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">The entire project can be found on GitHub here.<\/p>\n<p id=\"45f8\" class=\"pw-post-body-paragraph mn mo fr mp b mq mr ms mt mu mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk fk bj\" data-selectable-paragraph=\"\">Thanks for reading, cheers!<\/p>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Photo by Ian Taylor on Unsplash This article will comprehensively create, deploy, and execute machine learning application containers using the Docker tool. It will further explain the various containerization terms and the importance of this technology to the machine learning workflow. The article will contain hands-on sessions with practical coding examples as a use case. [&hellip;]<\/p>\n","protected":false},"author":114,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"customer_name":"","customer_description":"","customer_industry":"","customer_technologies":"","customer_logo":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[7],"tags":[],"coauthors":[211],"class_list":["post-8503","post","type-post","status-publish","format-standard","hentry","category-tutorials"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.9 (Yoast SEO v25.9) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Containerization of Machine Learning Applications - Comet<\/title>\n<meta name=\"description\" content=\"Learn how to create, deploy, and execute the containerization of machine learning applications using the Docker tool.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.comet.com\/site\/blog\/containerization-of-machine-learning-applications\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Containerization of Machine Learning Applications\" \/>\n<meta property=\"og:description\" content=\"Learn how to create, deploy, and execute the containerization of machine learning applications using the Docker tool.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.comet.com\/site\/blog\/containerization-of-machine-learning-applications\" \/>\n<meta property=\"og:site_name\" content=\"Comet\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/cometdotml\" \/>\n<meta property=\"article:published_time\" content=\"2023-12-26T16:00:48+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-04-24T17:03:42+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/miro.medium.com\/v2\/resize:fit:1000\/0*OO7o1QjrtFh696wI\" \/>\n<meta name=\"author\" content=\"Aboze Brain John Jnr\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@Cometml\" \/>\n<meta name=\"twitter:site\" content=\"@Cometml\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Aboze Brain John Jnr\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"32 minutes\" \/>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Containerization of Machine Learning Applications - Comet","description":"Learn how to create, deploy, and execute the containerization of machine learning applications using the Docker tool.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.comet.com\/site\/blog\/containerization-of-machine-learning-applications","og_locale":"en_US","og_type":"article","og_title":"Containerization of Machine Learning Applications","og_description":"Learn how to create, deploy, and execute the containerization of machine learning applications using the Docker tool.","og_url":"https:\/\/www.comet.com\/site\/blog\/containerization-of-machine-learning-applications","og_site_name":"Comet","article_publisher":"https:\/\/www.facebook.com\/cometdotml","article_published_time":"2023-12-26T16:00:48+00:00","article_modified_time":"2025-04-24T17:03:42+00:00","og_image":[{"url":"https:\/\/miro.medium.com\/v2\/resize:fit:1000\/0*OO7o1QjrtFh696wI","type":"","width":"","height":""}],"author":"Aboze Brain John Jnr","twitter_card":"summary_large_image","twitter_creator":"@Cometml","twitter_site":"@Cometml","twitter_misc":{"Written by":"Aboze Brain John Jnr","Est. reading time":"32 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.comet.com\/site\/blog\/containerization-of-machine-learning-applications#article","isPartOf":{"@id":"https:\/\/www.comet.com\/site\/blog\/containerization-of-machine-learning-applications\/"},"author":{"name":"Aboze Brain John Jnr","@id":"https:\/\/www.comet.com\/site\/#\/schema\/person\/9df9ece68642d6028b87b49a64fd7696"},"headline":"Containerization of Machine Learning Applications","datePublished":"2023-12-26T16:00:48+00:00","dateModified":"2025-04-24T17:03:42+00:00","mainEntityOfPage":{"@id":"https:\/\/www.comet.com\/site\/blog\/containerization-of-machine-learning-applications\/"},"wordCount":4761,"publisher":{"@id":"https:\/\/www.comet.com\/site\/#organization"},"image":{"@id":"https:\/\/www.comet.com\/site\/blog\/containerization-of-machine-learning-applications#primaryimage"},"thumbnailUrl":"https:\/\/miro.medium.com\/v2\/resize:fit:1000\/0*OO7o1QjrtFh696wI","articleSection":["Tutorials"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.comet.com\/site\/blog\/containerization-of-machine-learning-applications\/","url":"https:\/\/www.comet.com\/site\/blog\/containerization-of-machine-learning-applications","name":"Containerization of Machine Learning Applications - Comet","isPartOf":{"@id":"https:\/\/www.comet.com\/site\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.comet.com\/site\/blog\/containerization-of-machine-learning-applications#primaryimage"},"image":{"@id":"https:\/\/www.comet.com\/site\/blog\/containerization-of-machine-learning-applications#primaryimage"},"thumbnailUrl":"https:\/\/miro.medium.com\/v2\/resize:fit:1000\/0*OO7o1QjrtFh696wI","datePublished":"2023-12-26T16:00:48+00:00","dateModified":"2025-04-24T17:03:42+00:00","description":"Learn how to create, deploy, and execute the containerization of machine learning applications using the Docker tool.","breadcrumb":{"@id":"https:\/\/www.comet.com\/site\/blog\/containerization-of-machine-learning-applications#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.comet.com\/site\/blog\/containerization-of-machine-learning-applications"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.comet.com\/site\/blog\/containerization-of-machine-learning-applications#primaryimage","url":"https:\/\/miro.medium.com\/v2\/resize:fit:1000\/0*OO7o1QjrtFh696wI","contentUrl":"https:\/\/miro.medium.com\/v2\/resize:fit:1000\/0*OO7o1QjrtFh696wI"},{"@type":"BreadcrumbList","@id":"https:\/\/www.comet.com\/site\/blog\/containerization-of-machine-learning-applications#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.comet.com\/site\/"},{"@type":"ListItem","position":2,"name":"Containerization of Machine Learning Applications"}]},{"@type":"WebSite","@id":"https:\/\/www.comet.com\/site\/#website","url":"https:\/\/www.comet.com\/site\/","name":"Comet","description":"Build Better Models Faster","publisher":{"@id":"https:\/\/www.comet.com\/site\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.comet.com\/site\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.comet.com\/site\/#organization","name":"Comet ML, Inc.","alternateName":"Comet","url":"https:\/\/www.comet.com\/site\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.comet.com\/site\/#\/schema\/logo\/image\/","url":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2025\/01\/logo_comet_square.png","contentUrl":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2025\/01\/logo_comet_square.png","width":310,"height":310,"caption":"Comet ML, Inc."},"image":{"@id":"https:\/\/www.comet.com\/site\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/cometdotml","https:\/\/x.com\/Cometml","https:\/\/www.youtube.com\/channel\/UCmN63HKvfXSCS-UwVwmK8Hw"]},{"@type":"Person","@id":"https:\/\/www.comet.com\/site\/#\/schema\/person\/9df9ece68642d6028b87b49a64fd7696","name":"Aboze Brain John Jnr","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.comet.com\/site\/#\/schema\/person\/image\/02ed5776fb1ef41a0b234783f21f7460","url":"https:\/\/secure.gravatar.com\/avatar\/50122a5f71f7d0076d04e2bdb828dd78208d4c25c42bbae396b9783496f802a2?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/50122a5f71f7d0076d04e2bdb828dd78208d4c25c42bbae396b9783496f802a2?s=96&d=mm&r=g","caption":"Aboze Brain John Jnr"},"url":"https:\/\/www.comet.com\/site\/blog\/author\/411-codebraingmail-com\/"}]}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/posts\/8503","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/users\/114"}],"replies":[{"embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/comments?post=8503"}],"version-history":[{"count":1,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/posts\/8503\/revisions"}],"predecessor-version":[{"id":15413,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/posts\/8503\/revisions\/15413"}],"wp:attachment":[{"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/media?parent=8503"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/categories?post=8503"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/tags?post=8503"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/coauthors?post=8503"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}