<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Chris</title>
    <description>The latest articles on DEV Community by Chris (@christo22694524).</description>
    <link>https://dev.to/christo22694524</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F419999%2F488e36f7-3bb4-4501-8329-101483a11557.jpg</url>
      <title>DEV Community: Chris</title>
      <link>https://dev.to/christo22694524</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/christo22694524"/>
    <language>en</language>
    <item>
      <title>Publishing to a private Python repository with Poetry
</title>
      <dc:creator>Chris</dc:creator>
      <pubDate>Thu, 03 Feb 2022 11:02:01 +0000</pubDate>
      <link>https://dev.to/christo22694524/publishing-to-a-private-python-repository-with-poetry-3pl</link>
      <guid>https://dev.to/christo22694524/publishing-to-a-private-python-repository-with-poetry-3pl</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;In this article, we will look at &lt;a href="https://python-poetry.org/"&gt;Poetry&lt;/a&gt;, a tool for dependency management and packaging in Python, and how to publish a package built in Poetry to a private Python package manager hosted in &lt;a href="https://packagr.app"&gt;Packagr&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4sZUmec1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wfesfeqwdlzebunxgcnc.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4sZUmec1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wfesfeqwdlzebunxgcnc.jpeg" alt="Image description" width="880" height="659"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Poetry?
&lt;/h2&gt;

&lt;p&gt;Poetry describes itself as “Python packaging and dependency management made easy”. It combines the functionality of the standard python packaging tools &lt;code&gt;setuptools&lt;/code&gt; and &lt;code&gt;twine&lt;/code&gt;, allowing you to build and publish your Python package in a single command, while also managing your python package dependencies.&lt;/p&gt;

&lt;p&gt;By default, Poetry publishes built packages to the default public Python package repository, &lt;a href="https://pypi.org"&gt;PyPI&lt;/a&gt;. However, it is also possible to point poetry at your own private Python package server instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Provisioning a private Package repo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pjlKfAMY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o8zjiovahd5m9ecjukg1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pjlKfAMY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o8zjiovahd5m9ecjukg1.png" alt="Image description" width="368" height="105"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are several open-source solutions for provisioning your own, personal PyPI server — for example, this can be done using &lt;a href="https://pypi.org/project/pypiserver/"&gt;pypiserver&lt;/a&gt; or &lt;a href="https://github.com/devpi/devpi"&gt;devpi&lt;/a&gt;. However, configuring these services takes time and effort, and it costs money to deploy them. Instead, we’ll use &lt;a href="https://packagr.app"&gt;Packagr&lt;/a&gt;, a cloud-hosted python package server that allows you to provision your own private Python package repository. It also supports NPM packages and even Docker registries and is very easy to set up. You can get started by creating a free trial account on &lt;a href="https://app.packagr.app"&gt;Packagr&lt;/a&gt; — when you’ve created your account, you’ll see this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RD04MWke--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7l267hx8qju4etbwdybl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RD04MWke--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7l267hx8qju4etbwdybl.png" alt="Image description" width="880" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When your account is created, Packagr automatically generates a private repository URL for you. To find it click on &lt;strong&gt;Python packages&lt;/strong&gt; in the left-hand sidebar, then look for your unique &lt;strong&gt;Repository URL&lt;/strong&gt; towards the top of the page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xB0e_Tc8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kg2keutbiki05kdapoa3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xB0e_Tc8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kg2keutbiki05kdapoa3.png" alt="Image description" width="850" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The URL will be in the format &lt;strong&gt;&lt;code&gt;https://api.packagr.app/abcdef&lt;/code&gt;&lt;/strong&gt;. Make a note of your repository URL before continuing — you will need it later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Poetry
&lt;/h2&gt;

&lt;p&gt;Use this one-liner to install Poetry on your local machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may also need to configure your shell with the following command to complete the installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source $HOME/.poetry/env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check your installation worked with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry -v
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a package in Poetry
&lt;/h2&gt;

&lt;p&gt;Now that poetry is installed you can create a poetry project like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry new private-package
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a subfolder called &lt;code&gt;private-package&lt;/code&gt;, containing a package skeleton.&lt;/p&gt;

&lt;p&gt;And that’s it! We have created an empty Python package. We’re going to leave it blank for the sake of this simple tutorial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pointing Poetry at your private repository
&lt;/h2&gt;

&lt;p&gt;We can now configure Poetry to publish our &lt;code&gt;private-package&lt;/code&gt; package to our Packagr private repository by using the below command, replacing the URL with our unique Packagr repo URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry config repositories.packagr https://api.packagr.app/abcdef
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we can use the below command to store our Packagr credentials locally, meaning that we don’t have to enter them every time we want to publish the package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry config http-basic.packagr packagr-username@example.com password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Publishing the package to our private repository
&lt;/h2&gt;

&lt;p&gt;We’re now ready to publish! To do so, simply use this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry publish -r packagr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If all goes well, your private Python package will be uploaded successfully. You can confirm this by refreshing your Packagr UI:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VDqpMJpN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oxh8cr3k9jf5xnsuy5zt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VDqpMJpN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oxh8cr3k9jf5xnsuy5zt.png" alt="Image description" width="880" height="212"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing a private package with Poetry
&lt;/h2&gt;

&lt;p&gt;Now that we have published our Python package to a private repository, we can install it in other poetry projects. To do this, you’ll need to add this section to your &lt;code&gt;pyproject.toml&lt;/code&gt; (inserting your private repository URL):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[[tool.poetry.source]]
name = "packagr"
url = "https://api.packagr.app/abcdef"
secondary = true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;secondary = true&lt;/code&gt; bit is not essential here - however, if you have a project which has a lot of dependencies in PyPI as well, then resolving packages will take much less time.&lt;/p&gt;

&lt;p&gt;You can now do the following to install python packages locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry add private-package --source packagr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
      <category>devops</category>
      <category>cloud</category>
      <category>docker</category>
    </item>
    <item>
      <title>Installing private Python packages in Docker images</title>
      <dc:creator>Chris</dc:creator>
      <pubDate>Mon, 29 Jun 2020 19:04:36 +0000</pubDate>
      <link>https://dev.to/christo22694524/installing-private-python-packages-in-docker-images-1hgm</link>
      <guid>https://dev.to/christo22694524/installing-private-python-packages-in-docker-images-1hgm</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;In this tutorial, we’ll look at how to install a Python package stored in a private repo in a Docker image&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Let’s say you have a set of common Python utilities that you use across a number of different projects.&lt;/p&gt;

&lt;p&gt;For example, let’s say you have some scripts that generate random user data for the purpose of testing various applications, that you share across multiple projects&lt;/p&gt;

&lt;p&gt;Copying these scripts across multiple code bases is a nightmare from the perspective of maintenance, but these utilities may contain proprietary code that cannot be put somewhere public. So where can you put them?&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;One option is to package your utilities into a Python package, store the package in a private Python repository, then have the Docker image that contains your projects install these utilities from your repository. That way, you can easily control versioning of these utilities across all projects that have a dependency on them.&lt;/p&gt;

&lt;p&gt;In this tutorial, we’ll look out how to create a Python package, store it securely in a private repository (in this case, Packagr.app) and write a docker image that authenticates your private Python repository, then pulls and installs your package.&lt;/p&gt;

&lt;p&gt;For good measure, we’ll also store our built Docker image in Packagr.app&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical example
&lt;/h2&gt;

&lt;p&gt;For the purposes of this tutorial, we are going to build a simple tool that generates random user data, which we can use to populate APIs, perform tests, etc. Your utilities might do something totally different, but you can use the same approach to create a distributable package to do whatever you need, and store it privately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating your project
&lt;/h2&gt;

&lt;p&gt;Let’s start by creating our package. This tutorial assumes that you already have &lt;code&gt;python3&lt;/code&gt; and &lt;code&gt;virtualenv&lt;/code&gt; installed. Let’s create a folder called &lt;code&gt;data-generator&lt;/code&gt; and a virtual environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# create a directory and cd into it&lt;/span&gt;
&lt;span class="nb"&gt;mkdir &lt;/span&gt;data-generator &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;data-generator

&lt;span class="c"&gt;# create a virtual environment, and activate it&lt;/span&gt;
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv &lt;span class="nb"&gt;env
source env&lt;/span&gt;/bin/activate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, let’s create a subdirectory called &lt;code&gt;package&lt;/code&gt; that will store our code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;package
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let’s install Faker, a Python environment that generates random data&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;Faker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And let’s create a file called &lt;code&gt;process.py&lt;/code&gt; in the &lt;code&gt;package&lt;/code&gt; folder, which generates a random user every time it is called:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# process.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;faker&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Faker&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="n"&gt;fake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Faker&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_person&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;fake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;fake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;fake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;fake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above function simply outputs a dummy person in json format, that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Samuel Mendez&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;michelle71@hotmail.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*hMRsQBbK1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;address&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;78287 Morgan Summit&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Phillipsstad, WV 38051&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, lets create a folder called &lt;code&gt;bin&lt;/code&gt; in the root directory, and add a file called &lt;code&gt;make-person&lt;/code&gt;. This is a simple script that will let you call your function from the shell&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/usr/bin/env python
from package import process
process.generate_person()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, lets create a file called &lt;code&gt;setup.py&lt;/code&gt; in the root &lt;code&gt;data-generator&lt;/code&gt; directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;setuptools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;

&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'data-generator'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# the name of the package
&lt;/span&gt;    &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'1.0'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'package'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;# contains our actual code
&lt;/span&gt;    &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'chris'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;author_email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'chris@packagr.app'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'a random person generator'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;scripts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'bin/make-person'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;# the launcher script
&lt;/span&gt;    &lt;span class="n"&gt;install_requires&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'faker==2.0.2'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# our external dependencies
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Our folder structure should now look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/data-generator
    /package
        process.py
    /bin
        make-person
    setup.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We’re now ready to build our package! Enter the following lines into the command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# install wheel (to build packages in the bdist_wheel format)
pip install wheel
# create the package
python setup.py bdist_wheel
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The process will run, and a few additional folders will be created. The one we’re most interested in is the &lt;code&gt;dist&lt;/code&gt; folder, which contains our built package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;/dist
   data_generator-1.0-py3-none-any.whl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can check that our package works as expected by installing and running it as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# install the local package
pip install dist/*
# call the script
make-person
{"name": "Alexandra Nelson", "email": "sgarcia@yahoo.com", "password": "*c706Hvc+H", "address": "625 Powers Orchard\nNorth Bonnietown, IN 04475"}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Uploading the package to our private repository
&lt;/h2&gt;

&lt;p&gt;Now that we’ve built the package, we can upload it to our private repository. If you don’t already have a private repository to upload to, you can create one for free at &lt;a href="https://www.packagr.app"&gt;Packagr.app&lt;/a&gt; by following the simple sign up process. Once you’ve logged into your account, click on Create new package in the left hand menu to see your private repository URL — make a note of this, as you’ll need it later.&lt;/p&gt;

&lt;p&gt;Now that you’ve got a private repository, and a package, we can upload files to it. We do this using a tool called &lt;code&gt;twine&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# install twine&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;twine
&lt;span class="c"&gt;# upload your built package to your repository (update the URL as necessary)&lt;/span&gt;
twine upload  &lt;span class="nt"&gt;--repository-url&lt;/span&gt; https://api.packagr.app/63cdQSDO/ dist/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You’ll be prompted to enter credentials — just use the username and password you signed up for Packagr with. Once you’ve done that successfully, you’ll see your new package in your Packagr dashboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing your private package from inside a Docker container
&lt;/h2&gt;

&lt;p&gt;Now that our package is securely stored in our repository, let’s create a docker image capable of installing it. It’s important to remember that you should &lt;strong&gt;never store raw credentials in your Dockerfile&lt;/strong&gt;, or anywhere else in your code for that matter. So, you should pass your credentials as environmental variables at build time. With that in mind, let’s start by creating a file called requirements.txt in an empty folder, remembering to change the repository URL to your own :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--extra-index-url https://api.packagr.app/63cdQSDO/
data-generator==1.0.0
faker==2.0.2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;A requirements file is just a list of packages for pip to install. In this case, we are adding our private package, &lt;code&gt;data-generator&lt;/code&gt; and the public dependency, &lt;code&gt;faker&lt;/code&gt;. Adding the &lt;code&gt;--extra-index-url&lt;/code&gt; tells pip to look in our private repo, in addition to the public pypi.org one.&lt;/p&gt;

&lt;p&gt;Next, lets create our Dockerfile&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM python:3.7-alpine
ARG USER
ARG PASS
RUN echo "machine api.packagr.app \
         "    login ${USER} \
         "    password ${PASS}" &amp;gt; /root/.netrc
RUN chown root ~/.netrc
RUN chmod 0600 ~/.netrc
COPY requirements.txt /requirements.txt
RUN pip install -r requirements.txt
CMD make-person
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let’s take a detailed look at this, one line at a time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;FROM python:3.7-alpine&lt;/code&gt; tells Docker the base image to use — in this case we are using the lightweight alpine python distro, mostly to save time/space&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ARG USER&lt;/code&gt; and &lt;code&gt;ARG PASS&lt;/code&gt; defines variables that we will provide at build time — specifically, our Packagr username and password&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RUN echo...&lt;/code&gt; creates a file called .netrc which tells the image to use the Packagr username and password when connecting to api.packagr.app. The 2 following lines set the permissions of this file correctly&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COPY requirements...&lt;/code&gt; copies the requirements file to the Docker image&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RUN pip...&lt;/code&gt; installs the dependencies in our requirements file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CMD make-person&lt;/code&gt; just calls the script defined in our setup.py at run time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we have our Dockerfile, let’s build the Docker image, substituting in your Packagr username and password:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; dg-image &lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;chris@packagr.app &lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;PASS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;changeme &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If all goes well, your docker image should build correctly! We can now upload it to our docker registry. Go back to the Packagr interface, click on Docker registry, and make a note of your Docker registry URL - it should be similar to your Python package repo URL, but with &lt;strong&gt;docker.packagr.app&lt;/strong&gt; instead of the domain, and with the hash id in lowercase characters.&lt;/p&gt;

&lt;p&gt;The first step is to login to docker — as usual, you’ll need to update the URL, username and password to your own&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker login docker.packagr.app/63cdqsdo -u me@example.com -p changeme
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, you’ll need to tag the image you just build (again, change the URL)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;docker tag dg-image docker.packagr.app/63cdqsdo/dg-image:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, you can push your tags:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker push docker.packagr.app/63cdqsdo/dg-image:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You should now see your image in your docker registry in Packagr. You can now pull this docker image from any other machine you are logged into with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull docker.packagr.app/63cdqsdo/dg-image:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>python</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
