<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
<title type="text">Alden Jenkins</title>
<subtitle type="text">Developer, Debugger, &amp; Deployer</subtitle>
<generator uri="https://github.com/mojombo/jekyll">Jekyll</generator>
<link rel="self" type="application/atom+xml" href="https://aldenjenkins.com/feed.xml" />
<link rel="alternate" type="text/html" href="https://aldenjenkins.com" />
<updated>2023-02-14T19:06:11-05:00</updated>
<id>https://aldenjenkins.com/</id>
<author>
  <name>Alden Jenkins</name>
  <uri>https://aldenjenkins.com/</uri>
</author>


<entry>
  <title type="html"><![CDATA[Omnipotent Service Level Indicators]]></title>
  <link rel="alternate" type="text/html" href="https://aldenjenkins.com/blog/omnipotent-service-level-indicators/" />
  <id>https://aldenjenkins.com/blog/ensuring-you-are-meeting-your-slos</id>
  <published>2019-02-11T00:00:00-05:00</published>
  <updated>2019-02-11T00:00:00-05:00</updated>
  <author>
    <name>Alden Jenkins</name>
    <uri>https://aldenjenkins.com</uri>
  </author>
  <content type="html">&lt;p&gt;Your SLOs (Service Level Objectives) are what keep making your company money, and
what keep you honest as a deployer of your application. At it’s core, an SLO is simply
an objective of a specific attribute of your service such as availability, throughput,
response time, etc.&lt;/p&gt;

&lt;p&gt;Without ensuring that the SLOs you are creating are met as time
progresses, you’ll run into angry customers, tarnishing the relationship that you had with 
them up
to that point. At the same time, you will facilitate underconfident employees who will
feel that the loss of your customer due to an error in service
was either their personal fault, or that your mistakes as their leader are now
compromising their job security by creating potential
revenue uncertainty for the company. The solution to ensuring that your SLOs are met is simply an
investment of time in optimizing your SLIs (Service Level Indicators).&lt;/p&gt;

&lt;p&gt;Within the deployment of &lt;a href=&quot;https://metoo.io&quot;&gt;metoo.io&lt;/a&gt;, we use creative SLIs to give
us reliable metrics throughout our deployment environments. We capture &lt;strong&gt;ALL&lt;/strong&gt;
of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Telemetry&quot;&gt;telemetry&lt;/a&gt; between our microservices and scrape the metrics with Prometheus
so that we can graph the data using Grafana, and perform other queries
on the data when required. Grafana is awesome because it allows
us to create multiple dashboards for simultaneous viewing which Prometheus does
not support out of the box.&lt;/p&gt;

&lt;p&gt;Beyond Grafana, we run AlertManager with custom rules
for alerting us when our SLOs are not being met. Our SLO for uptime is a 4 nine 
SLO (99.99% uptime,) and use AlertManager to tell us when our past 10 minute
SLO has not been met. We run a Prometheus query for each environment to check 
whether &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!(200 &amp;lt;= response status codes &amp;lt; 404)&lt;/code&gt; start to occur for more than 
0.01% of responses, and other queries regarding communication between services.
But how are we able to collect so much telemetry in the first place?&lt;/p&gt;

&lt;p&gt;Enter &lt;a href=&quot;https://istio.io/&quot;&gt;Istio&lt;/a&gt;! This Service Mesh for Kubernetes allows us to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Secure communication between pods using mTLS (beneficial for cross-cloud deployments)&lt;/li&gt;
  &lt;li&gt;Automatically collect Telemetry between pods,&lt;/li&gt;
  &lt;li&gt;Give every pod an L7 reverse proxy SideCar container (Envoy Proxy,) which reads from the Istio
  Global Virtual Service rules and Routing rules to give us the ability to:
    &lt;ul&gt;
      &lt;li&gt;Route a dynamically specified amount of trafic to our staging environment,&lt;/li&gt;
      &lt;li&gt;Route arbitrary device types to an environment of our choice as recorded
  by the L7 reverse proxy.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since these specifications are all specified in deployment yaml files, it becomes
easy to listen to a webhook sent by AlertManager regarding a 500 (or other status
code) response coming from your Canary Environment and then automatically apply a&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'s/weight: 10/weight: 0/'&lt;/span&gt; routing-canary.yaml &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; kubectl apply &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; routing-canary.
yaml &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;change, making your SLIs literally a self-healing omnipotent force in your
DevOps arsenal!!!!! &amp;gt;:D&lt;/p&gt;


  &lt;p&gt;&lt;a href=&quot;https://aldenjenkins.com/blog/omnipotent-service-level-indicators/&quot;&gt;Omnipotent Service Level Indicators&lt;/a&gt; was originally published by Alden Jenkins at &lt;a href=&quot;https://aldenjenkins.com&quot;&gt;Alden Jenkins&lt;/a&gt; on February 11, 2019.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Deploying GeoDjango in an Alpine Linux Docker Container]]></title>
  <link rel="alternate" type="text/html" href="https://aldenjenkins.com/blog/geodjango-alpine-docker/" />
  <id>https://aldenjenkins.com/blog/dockerizing-geodjango-to-alpine-linux</id>
  <published>2019-01-19T00:00:00-05:00</published>
  <updated>2019-01-19T00:00:00-05:00</updated>
  <author>
    <name>Alden Jenkins</name>
    <uri>https://aldenjenkins.com</uri>
  </author>
  <content type="html">&lt;p&gt;In deploying &lt;a href=&quot;https://metoo.io&quot;&gt;metoo.io&lt;/a&gt; with Kubernetes, I wanted to reduce the time
from launching a new deployment until the deployment was live as short as
possible. In the beginning, metoo was containerized using the typical uncomplicated method
of using an Ubuntu Docker image like most other GeoDjango builds. While the image
worked fine, the image size was ~600MB. But why is this size an issue?&lt;/p&gt;

&lt;p&gt;Smaller containers simply download and deploy faster than larger ones. While we
already use Google Compute Engine for our remote servers, we found it easy to decide
that we would store our Docker images in GCR instead of Dockerhub. This was because
GCR allows for free
storage and transfer to nodes within Google’s data centers. Additionally, polling GCR
for container downloads on GKE servers hosted inside those same data centers inherently
makes container download much faster.&lt;/p&gt;

&lt;p&gt;While Ubuntu is not necessarily the &lt;strong&gt;most&lt;/strong&gt; bloated operating system you could run inside
Docker container, there is 
definitely room for improvement. Under further investigation, Alpine Linux was
the most minimal while being (almost) fully-compatible-with-GeoDjango operating systems
you could choose from. Compared with Ubuntu’s size of 600MB, Alpine sported a size of
just ~200MB. We saw improvements of deployment times of just over 1 minute with Ubuntu images
down to just about 10 seconds using Alpine.&lt;/p&gt;

&lt;h3 id=&quot;considerations&quot;&gt;Considerations&lt;/h3&gt;
&lt;p&gt;There are a few considerations you want to make in deciding whether or not to 
switch to alpine or not.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Be prepared to have a test suite to run after deploying.
    &lt;ul&gt;
      &lt;li&gt;Understand that since you are likely not developing on the same Alpine Linux Environment,
  that you’re deploying on, there may be dependency issues that do not arise until you
  run the container and check literally everything that can be checked with your 
  deployment. This is both a good thing and a bad thing because it will keep you
  honest about testing all of your code but will also really slap you in the face
  if you accidentally forget to test something which breaks. For example, we had a very
  outlandish error arise when we were using a specific GeoDjango admin module which
  would crash the server on our Alpine build when viewing an admin page that rendered
  a point on a map which didn’t occur on my Arch development environment.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If you are hosting an open source application that you want to be
  easily accessible to others, recognize that Alpine is much harder for the laymen
  programmer to work with.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Dependency Issues arise frequently and out of nowhere
    &lt;ul&gt;
      &lt;li&gt;Anticipate for the worst case that you are going to run into a build issue at least once 
  every 6 months at the cost of the smaller image size.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;alpine-with-geodjango&quot;&gt;Alpine with GeoDjango&lt;/h2&gt;

&lt;p&gt;No released version of Alpine came with either the GEOS or GDAL libraries available
for installation, and only the experimental &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;edge&lt;/code&gt; version of alpine to this day has
the packages downloadable. To solve for this, I build the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python:alpine&lt;/code&gt; docker image
from scratch within my Dockerfile then added the required build dependencies manually in a separate
run layer.&lt;/p&gt;

&lt;p&gt;Feel free to use the code for your GeoDjango Deployments and spread the love! :D&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-go&quot; data-lang=&quot;go&quot;&gt;&lt;span class=&quot;n&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alpine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;3.8&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;This&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sets&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;remote&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inside&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;etc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;apk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;repositories&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;which&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;we&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;will&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;manually&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;later&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;edge&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
 
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ensure&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;preferred&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;over&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;distribution&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;python&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ENV&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PATH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;usr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;local&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PATH&lt;/span&gt;

&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;//bugs.python.org/issue19846&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;At&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;moment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setting&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;LANG=C&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Linux&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;system&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fundamentally&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;breaks&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Python&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ENV&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LANG&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UTF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;8&lt;/span&gt;

&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ca&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;certificates&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;so&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HTTPS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;works&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;consistently&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;runtime&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dependencies&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Python&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;are&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;installed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;later&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;RUN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;no&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cache&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ca&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;certificates&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;ENV&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GPG_KEY&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;C01E1CAD5EA2C4F0B8E3571504C367C218ADD4FF&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ENV&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PYTHON_VERSION&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2.7.14&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;RUN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ex&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
   	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;no&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cache&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deps&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;gnupg&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;openssl&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;xz&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wget&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;O&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;python&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xz&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz&quot;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wget&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;O&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;python&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xz&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;asc&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz.asc&quot;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GNUPGHOME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;$(mktemp -d)&quot;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gpg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keyserver&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ha&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keyservers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;net&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;recv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;$GPG_KEY&quot;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gpg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;batch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;verify&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;python&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xz&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;asc&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;python&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xz&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rf&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;$GNUPGHOME&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;python&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xz&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;asc&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;usr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xJC&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;usr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;python&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xz&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;python&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xz&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;no&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cache&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deps&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;bzip2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;coreutils&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;dpkg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dpkg&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;gcc&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;gdbm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;libc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;linux&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;headers&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;nb&quot;&gt;make&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;ncurses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;openssl&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;openssl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;pax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;utils&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;readline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;sqlite&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;tcl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;tk&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;tk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;zlib&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deps&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;before&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;removing&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fetch&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deps&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;there&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;overlap&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;del&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deps&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;usr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gnuArch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)&quot;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;./&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;configure&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;$gnuArch&quot;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unicode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ucs4&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;make&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;$(nproc)&quot;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;thread&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MB&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;so&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;we&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;don&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;segfault&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;before&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;we&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getrecursionlimit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;https&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;//github.com/alpinelinux/aports/commit/2026e1259422d4e0cf92391ca2d3844356c649d0&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;EXTRA_CFLAGS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;-DTHREAD_STACK_SIZE=0x100000&quot;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;make&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;runDeps&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;$( &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
		scanelf --needed --nobanner --format '%n#p' --recursive /usr/local &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
			| tr ',' '&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;' &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
			| sort -u &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
			| awk 'system(&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;usr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;local&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lib&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot; $1 &quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;) == 0 { next } { print &quot;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;so&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot; $1 }' &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
	)&quot;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;python&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rundeps&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runDeps&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;del&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deps&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;usr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;depth&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
			&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tests&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
			&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pyc&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pyo&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rf&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;usr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;python&lt;/span&gt;

&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;called&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;PIP_VERSION&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pip&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;explodes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ValueError: invalid truth value '&amp;lt;VERSION&amp;gt;'&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ENV&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PYTHON_PIP_VERSION&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;9.0.1&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;RUN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;apk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;no&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cache&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deps&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;openssl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;wget&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;O&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pip&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;py&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;https&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;//bootstrap.pypa.io/get-pip.py'; \&lt;/span&gt;
	&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;apk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;del&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pip&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;py&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pip&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;no&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;s&quot;&gt;&quot;pip==$PYTHON_PIP_VERSION&quot;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;pip&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;usr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;depth&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
			&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tests&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
			&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pyc&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pyo&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rf&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pip&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;py&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;

&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Project&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;specific&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dependencies&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;COPY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;./&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;requirements&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;txt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;

&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GeoDjango&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dependencies&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ENV&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PACKAGES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
    alpine-sdk &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
    libffi-dev &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
    jpeg-dev &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
    python-dev &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
    zlib-dev &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
    musl-dev &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
    libffi &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
    postgresql-dev &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;RUN&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;apk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deps&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;no&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cache&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upgrade&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PACKAGES&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
   	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;http://dl-cdn.alpinelinux.org/alpine/edge/testing&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;etc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;apk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;repositories&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
   	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;http://dl-cdn.alpinelinux.org/alpine/edge/community&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;etc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;apk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;repositories&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
   	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;http://dl-cdn.alpinelinux.org/alpine/edge/main&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;etc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;apk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;repositories&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;gdal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;geos&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deps&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;postgresql&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;libs&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pip&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upgrade&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pip&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pip&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requirements&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;txt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;no&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apk&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;purge&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;del&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deps&lt;/span&gt;

&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;application&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;COPY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;WORKDIR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;metoo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;backend&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;CMD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gunicorn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;8080&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wsgi&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;


  &lt;p&gt;&lt;a href=&quot;https://aldenjenkins.com/blog/geodjango-alpine-docker/&quot;&gt;Deploying GeoDjango in an Alpine Linux Docker Container&lt;/a&gt; was originally published by Alden Jenkins at &lt;a href=&quot;https://aldenjenkins.com&quot;&gt;Alden Jenkins&lt;/a&gt; on January 19, 2019.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Alpine Linux is Mandatory]]></title>
  <link rel="alternate" type="text/html" href="https://aldenjenkins.com/blog/alpine-linux/" />
  <id>https://aldenjenkins.com/blog/alpine-linux-is-suckless</id>
  <published>2019-01-19T00:00:00-05:00</published>
  <updated>2019-01-19T00:00:00-05:00</updated>
  <author>
    <name>Alden Jenkins</name>
    <uri>https://aldenjenkins.com</uri>
  </author>
  <content type="html">&lt;p&gt;Alpine Linux can be one of the most useful tools in your DevOps arsenal once you know how to use it.&lt;/p&gt;

&lt;p&gt;Depending on the complexity of your use case, it will be a true test of your Docker skills and once you get it down you will have learned so much
along the way… or you may just be able to use a default image and be fine with no hassle! Regardless here you’ll learn what the
hype about Alpine Linux containers is all about and how you can go about creating them when you need to.&lt;/p&gt;

&lt;p&gt;You’ve probably seen a lot of Docker image tags ending in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:alpine&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:alpine-3.8&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:alpine-edge&lt;/code&gt;, and are wondering
what the heck those mean. At its core, Alpine Linux is a much more &lt;strong&gt;minimal&lt;/strong&gt; Linux distribution that does not
come with as many built-in features. This is intended though, because &lt;em&gt;with less of what you don’t need
you can build the image to have only what you do need&lt;/em&gt;. This helps cuts down the size of your images
which ultimately decreases the time that it takes to start your containers. Additionally your container will be optimized to run
operations only useful for your application. This means no Bloat-ware that takes up your system 
resources in these containers!&lt;/p&gt;

&lt;p&gt;This is what makes Alpine &lt;a href=&quot;https://suckless.org/&quot;&gt;Suckless&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For most of you that can use a standard docker image for your use case like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python:3-alpine&lt;/code&gt;, that is all
you really need to know about Alpine because all of the build work is already done for you. For the rest
of you who need to know how it works, strap in!&lt;/p&gt;

&lt;p&gt;Let’s take a look at an example Alpine Dockerfile that builds all of the system libraries and dependencies
that you need to run curl&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-go&quot; data-lang=&quot;go&quot;&gt;&lt;span class=&quot;n&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alpine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;3.8&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;RUN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;no&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cache&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curl&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;ENTRYPOINT&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/usr/bin/curl&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--no-cache&lt;/code&gt; option for the apk package manager is important because it allows all of the source files
used to build the shared objects and executables to be deleted from the system after building. This means that you will
only be left with the executables after the command runs. This can be an issue for specific builds where
the libraries of certain packages are required to build or use other packages.&lt;/p&gt;

&lt;p&gt;The solution to this problem is to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--virtual&lt;/code&gt; option when installing apk packages which
allows you to specify a virtual directory to temporarily store all of the libraries, source code, and executables inside of
and manually delete that directory after you’ve built the package that you need by running
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apk del .dir-name&lt;/code&gt; at any point in the image build process that you would like. Or, if you need
those libraries and shared objects during production usage, you can simply run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apk add package-name&lt;/code&gt;
and it will keep everything like a normal package manager would.&lt;/p&gt;

&lt;p&gt;Consider installing vim which requires gcc to build:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-go&quot; data-lang=&quot;go&quot;&gt;&lt;span class=&quot;n&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alpine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;3.8&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;RUN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deps&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gcc&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;del&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deps&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;ENTRYPOINT&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/usr/bin/vim&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here you download and build gcc and then build vim but are only left with the vim executable
because you delete the directory where gcc was installed and now gcc is no longer installed&lt;/p&gt;

&lt;p&gt;This is the crux of most peoples strife’s with Alpine Linux: build dependency issues. Since Alpine
is able to give you such small images, it sometimes has to compromise with compatibility with
specific packages, and when packages update and you’re building using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:alpine-latest&lt;/code&gt;, you’re in for
some big trouble if those packages don’t. Better hope you have your Docker build layers cached up to 
that point in the Dockerfile!&lt;/p&gt;

&lt;p&gt;The art of creating a good, minimal Alpine Linux container comes from being very intimate with
your library versions and build requirements. The only thing that will help you with this is practice,
so go try making an alpine version of your build!&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://aldenjenkins.com/blog/alpine-linux/&quot;&gt;Alpine Linux is Mandatory&lt;/a&gt; was originally published by Alden Jenkins at &lt;a href=&quot;https://aldenjenkins.com&quot;&gt;Alden Jenkins&lt;/a&gt; on January 19, 2019.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Pair Programming from Anywhere on Earth over SSH]]></title>
  <link rel="alternate" type="text/html" href="https://aldenjenkins.com/blog/pair-programming/" />
  <id>https://aldenjenkins.com/blog/pair-programming-from-anywhere-in-the-world-over-ssh</id>
  <published>2018-12-10T00:00:00-05:00</published>
  <updated>2018-12-10T00:00:00-05:00</updated>
  <author>
    <name>Alden Jenkins</name>
    <uri>https://aldenjenkins.com</uri>
  </author>
  <content type="html">&lt;p&gt;Let’s admit it: &lt;em&gt;We all hate pair programming&lt;/em&gt;, but we have to admit it is effective. 
In pair programming, we are always exposing ourselves to new methods of programming
and are given the opportunity to challenge our own ideas to bring the best solutions
to fruition.  The fact of the matter is that Pair programming always helps atleast one of the parties involved by 
teaching one in the pair something or providing a new perspective for the most efficient means
to complete a task.&lt;/p&gt;

&lt;h2 id=&quot;the-issue&quot;&gt;The Issue&lt;/h2&gt;
&lt;p&gt;Now most of the time we like the person we’re working with, or can atleast tolerate them in person.
But in some cases, they are impossible to be around in person! If you’re experiencing the latter (or just
prefer to pair program remotely – a much more realistic scenario which also comes with plenty of 
inherent convenience,) then this tutorial is for you.&lt;/p&gt;

&lt;h2 id=&quot;solutions&quot;&gt;Solutions&lt;/h2&gt;
&lt;p&gt;There are a couple types of solutions which allow for being able to pair program remotely.&lt;/p&gt;

&lt;h3 id=&quot;facetime-or-other-videoscreen-sharing-solution&quot;&gt;Facetime (or other video/screen sharing solution):&lt;/h3&gt;

&lt;p&gt;Perhaps the most archaic solution, coding over video chat often leaves one person doing most of the work
 and the other person squinting at where the other person’s cursor is. This is the solution most conducive to YATS
 (Yelling At The Screen) when you’re trying to get your partners attention as they’re scrolling through a file and you
 see the piece of code you were scanning for.&lt;/p&gt;

&lt;h3 id=&quot;code-sharing-websites-like-google-docs&quot;&gt;Code Sharing websites like Google Docs&lt;/h3&gt;
&lt;p&gt;While Facetime solutions succeeds in the personal connection aspect, they fail in being able to allow for easy
contribution to the code from either party in the partnership. If you wanted to change the code over voice call,
you would need to tell your partner what to change exactly.&lt;/p&gt;

&lt;h2 id=&quot;the-best-of-both-worlds&quot;&gt;The Best of both worlds&lt;/h2&gt;

&lt;p&gt;Where Code sharing websites succeed, Video sharing solutions fail, and vice versa. You can’t both code at the same time while also being able to see and talk to each
other at the same time. The following allows for the best of both worlds, from anywhere in the world.&lt;/p&gt;

&lt;h3 id=&quot;using-tmux-over-ssh-combined-with-appearin&quot;&gt;Using Tmux over SSH combined with Appear.in&lt;/h3&gt;
&lt;p&gt;The SSH protocol allows for secure access to your code base from anywhere in the world. Think of it like traveling to your house in an armored car in layman terms.
Your data could still be stolen, but it would be insurmountably more difficult to do as opposed to if you were using an insecure transport method (im looking at you Telnet!)&lt;/p&gt;

&lt;p&gt;Once you’ve SSH’d into your server, the &lt;a href=&quot;https://www.systutorials.com/docs/linux/man/1-tmux/&quot;&gt;Tmux&lt;/a&gt; application allows a vast expanse of applicable usages besides pair programming.&lt;/p&gt;

&lt;p&gt;It can be used as:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;A more feature-filled replacement for the popular &lt;strong&gt;Nohup&lt;/strong&gt; alternative &lt;strong&gt;Screen&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;A Terminal screen multiplexer (points to the the name TMUX)&lt;/li&gt;
  &lt;li&gt;A Pair Programming solution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tmux runs a local server which runs any number of terminals that you like. The key here is that the local server can be attached to and disconnected from.&lt;/p&gt;

&lt;h3 id=&quot;see-it-in-action&quot;&gt;See it in action!&lt;/h3&gt;
&lt;figure&gt;
&lt;script src=&quot;https://asciinema.org/a/7JD45Xi4Zs4dR9oLxn2iWjODg.js&quot; id=&quot;asciicast-7JD45Xi4Zs4dR9oLxn2iWjODg&quot; async=&quot;&quot;&gt;&lt;/script&gt;
   &lt;figcaption&gt;Me attaching and detatching from one of my two live Tmux sessions at will.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The issue here is that to be able to connect to User1’s Tmux session, you must also be logged in as User1.&lt;/p&gt;

&lt;p&gt;While most people who pair program together have no problem extending the trust needed to share their password to one another,
some people don’t like that level of commitment. This is not an issue! You can use SSH keys to control who has access to your
user.&lt;/p&gt;

&lt;p&gt;Once someone has an SSH Key to your server, they can simply login using that key in lieu of a password. To delegate someone an SSH key, have them first create a Public/Private key pair using the following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh-keygen -t rsa -C &quot;your_email@example.com&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The Password which it asks you to fill out can be ignored or filled depending on whether you feels he won’t let anyone else gain
access to the key they just produced. If they’re the type that’s usually late for work after the night of the Powerball winner announcement, they better have a password on their key!
This password acts as the second factor of Two-factor auth because the authentication requires &lt;strong&gt;something you have&lt;/strong&gt; (the newly generated key) and &lt;strong&gt;something you know&lt;/strong&gt; (the aforementioned
password which decrypts the key)&lt;/p&gt;

&lt;p&gt;Have the key creator give you the .pub public key which was created from the previous command output and place the contents of that key
in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME/.ssh/authorized_keys&lt;/code&gt; file and then restart your SSH service by running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo service ssh restart&lt;/code&gt;. Your SSH process is now loaded
with the understanding that anyone who connects with a private key which when &lt;a href=&quot;https://security.stackexchange.com/questions/45963/diffie-hellman-key-exchange-in-plain-english&quot;&gt;Diffie-Hellmann’d&lt;/a&gt;
with your public key in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;authorized_keys&lt;/code&gt; should result in an affirmative value should be allowed access to your user.&lt;/p&gt;

&lt;p&gt;You can control who has access to your user based on the public keys listed in authorized keys. Want to prevent someone from logging in?
Simply remove their entry in the file.&lt;/p&gt;

&lt;p&gt;To attach to a running Tmux session as shown above, you can run&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tmux a
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;if there is only one session running. Or to pick a specific session,
you can run&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tmux ls
# Results shown here
tmux a -t &amp;lt;session number picked from above results&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;While each of you now has easy access to your compile scripts, and the rest of the codebase, and direct system terminal access, the issue of no video/audio personal connection
still exists.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://appear.in&quot;&gt;Appear.in&lt;/a&gt; is the perfect solution. appear.in allows for audio, video, and screen sharing communication all within the browser.
No other solution provides the same functionality while also being totally free.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

&lt;h2 id=&quot;honorable-mentions&quot;&gt;Honorable Mentions&lt;/h2&gt;

&lt;p&gt;The vim plugin &lt;a href=&quot;https://github.com/FredKSchott/CoVim&quot;&gt;CoVim&lt;/a&gt;, developed by Tufts Computer Scientists, allows for pair programming through vim sessions.
The downfall to this is that you must compile your vim from source with python support if it does not already have it, and you also only have access to
your partner’s vim session &lt;em&gt;instead of their entire terminal&lt;/em&gt;. This means that you do not have access to the rest
of the codebase outside of vims !command functionality, which is limiting in usability. You can read more about CoVim
&lt;a href=&quot;http://fredkschott.com/post/2013/05/introducing-covim-real-time-collaboration-for-vim/&quot;&gt;in their announcement post here&lt;/a&gt;!&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://aldenjenkins.com/blog/pair-programming/&quot;&gt;Pair Programming from Anywhere on Earth over SSH&lt;/a&gt; was originally published by Alden Jenkins at &lt;a href=&quot;https://aldenjenkins.com&quot;&gt;Alden Jenkins&lt;/a&gt; on December 10, 2018.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[How metoo works]]></title>
  <link rel="alternate" type="text/html" href="https://aldenjenkins.com/blog/how-metoo-works/" />
  <id>https://aldenjenkins.com/blog/how-metoo-works</id>
  <published>2018-11-27T00:00:00-05:00</published>
  <updated>2018-11-27T00:00:00-05:00</updated>
  <author>
    <name>Alden Jenkins</name>
    <uri>https://aldenjenkins.com</uri>
  </author>
  <content type="html">&lt;p&gt;&lt;a href=&quot;https://metoo.io&quot;&gt;metoo.io&lt;/a&gt; is the largest, most complex web service I have ever deployed.
It’s a really cool app, and I’m not just saying that because I made it. If you have a chance you
should absolutely check it out.&lt;/p&gt;

&lt;figure&gt;
	&lt;img src=&quot;https://camo.githubusercontent.com/e45e39c36eebcc4c66e1aecd4e4145112d8e88e3/687474703a2f2f692e696d6775722e636f6d2f6a6a3341354e382e706e67&quot; /&gt;
	&lt;figcaption&gt;Image courtesy of donnemartin &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;In deploying a stack, you want to be mostly certain of the way that you deploy it from the beginning,
because certain containers begin to rely on the minutae of what its input from another API looks like and
changing that is not as streamlined as one would like. If you are looking for a stack to replicate, you
should be comfortable choosing the following applications for their current bleeding-egde reputations.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Reverse Proxy: &lt;strong&gt;Nginx&lt;/strong&gt; lets us use &lt;a href=&quot;https://letsencrypt.org/&quot;&gt;LetsEncrypt&lt;/a&gt;, a free and open Certificate Authority which
also allows us to generate free TLS Certificates for each of our subdomains, all while still maintaining a &lt;a href=&quot;https://www.ssllabs.com/&quot;&gt;SSL Labs&lt;/a&gt; A+ rating.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Backend Framework: &lt;strong&gt;Django REST&lt;/strong&gt; allows us to use the highly scalable Python Web framework 
  while sending JSON data as response requests. This works perfectly in conjunction with our app’s frontend &lt;a href=&quot;https://facebook.github.io/react-native/&quot;&gt;React Native&lt;/a&gt;
  which injests JSON as input.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Frontend Framework: &lt;strong&gt;React Native&lt;/strong&gt; allows us to deploy to androids and iPhones seemlessly all
  while using Javascript, a forgiving, highl level, weakly typed language that’s &lt;em&gt;relatively&lt;/em&gt; 
  easy to debug.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Relational Database Management System: &lt;strong&gt;PostGreSQL&lt;/strong&gt; with the &lt;strong&gt;PostGIS&lt;/strong&gt; extension allows us to
  use geolocational data.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Cache: &lt;strong&gt;Redis&lt;/strong&gt; is our highly scalable, master-slave ready, in-memory cache. We chose redis over memcached due to
  more support in Django.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Asynchronous task completion: &lt;strong&gt;Celery&lt;/strong&gt; allows us to use run non-blocking tasks such as sending texts,
  emails, or creating notification objects outside of the user’s request.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Task Message Broker: &lt;strong&gt;RabbitMQ&lt;/strong&gt; - as opposed to using Redis as a message broker - allows us to
  persist tasks even in the off chance that RabbitMQ needs to be restarted. Redis does not
  allow for this.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Containerization Strategy: &lt;strong&gt;Docker&lt;/strong&gt; means we deploy each of the above strategies as
  microservices and then orchestrate them in a production environment using &lt;a href=&quot;https://kubernetes.io/&quot;&gt;Kubernetes&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Orchestration Strategy: &lt;strong&gt;Kubernetes&lt;/strong&gt; allows for zero downtime of the service through deployment
  updates and potential rollbacks.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Profiling: &lt;a href=&quot;https://github.com/jazzband/django-silk&quot;&gt;Django Silk&lt;/a&gt; Is an open source profiler for django
  which creates models in your applications database which can be updated on a variable scale and lets
  us see where bottlenecks in certain views occur, or where &lt;a href=&quot;http://blog.scoutapp.com/articles/2018/04/30/finding-and-fixing-n-1s-in-django-apps&quot;&gt;N+1&lt;/a&gt; issues
  arise.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Error Reporting: &lt;strong&gt;Sentry.io&lt;/strong&gt; is an entirely open source service that allows us to setup our own
  sentry service as a container of one of our GKE nodes.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Replicas: Due to the nature of microservices being extremely portable, it’s so easy to scale
  each of the above services to infinity based on the current required need. For example, say we
  need far more Asynchronous task workers deployed because we are currently undergoing a large amount
  of user signups and we need to be able to send a large amount of notifications to friends of the
  user signing up, emails, etc.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we have our stack up and running, we would want in the most ideal circumstance to be able
to access various data pertaining to each node, and pod container. For this, we deployed a &lt;strong&gt;stat stack&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;First, we need a data aggregating tool. There are plenty of choices from &lt;a href=&quot;https://github.com/etsy/statsd&quot;&gt;StatsD&lt;/a&gt; to &lt;a href=&quot;https://www.influxdata.com/&quot;&gt;influxDB&lt;/a&gt; to &lt;a href=&quot;https://prometheus.io/&quot;&gt;Prometheus&lt;/a&gt;, but
we decided to go with Prometheus.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Prometheus allows us to aggregate data into a queryable format and also provides an API from which we use
&lt;a href=&quot;https://grafana.com/&quot;&gt;Grafana&lt;/a&gt; to scrape from.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Grafana is originally a &lt;a href=&quot;https://graphiteapp.org/&quot;&gt;graphite&lt;/a&gt; extension that allows graphing a wide variety of data sources
  ranging from Prometheus, to a PostgreSQL or MySQL instance.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Additionally we use &lt;a href=&quot;https://github.com/prometheus/node_exporter&quot;&gt;Node-exporter&lt;/a&gt;, &lt;a href=&quot;https://github.com/google/cadvisor&quot;&gt;cAdvisor&lt;/a&gt;, 
  and &lt;a href=&quot;https://prometheus.io/docs/alerting/alertmanager/&quot;&gt;Alertmanager&lt;/a&gt; for Prometheus to scrape from.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I would absolutely recommend the same or similar stack to anyone who wants to create a reliable,
highly scalable infrastructure for their webservice or similar application, the ease of knowing that
everything &lt;em&gt;just works&lt;/em&gt; is just another reason that living in 2018 is something to be appreciative of.
It’s the most bleeding edge of technological advancement which we have available to us today, and it’s
only going to get more mainstreamed from here.&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://aldenjenkins.com/blog/how-metoo-works/&quot;&gt;How metoo works&lt;/a&gt; was originally published by Alden Jenkins at &lt;a href=&quot;https://aldenjenkins.com&quot;&gt;Alden Jenkins&lt;/a&gt; on November 27, 2018.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Stop Using Disqus]]></title>
  <link rel="alternate" type="text/html" href="https://aldenjenkins.com/blog/stop-using-disqus/" />
  <id>https://aldenjenkins.com/blog/stop-using-disqus</id>
  <published>2018-10-24T00:00:00-04:00</published>
  <updated>2018-10-24T00:00:00-04:00</updated>
  <author>
    <name>Alden Jenkins</name>
    <uri>https://aldenjenkins.com</uri>
  </author>
  <content type="html">&lt;p&gt;Disqus is gaining popularity every day in both the &lt;a href=&quot;https://aldenjenkins.com/blog/this-blog-is-completely-serverless&quot;&gt;serverless&lt;/a&gt; and dynamic web communities
because it is a mostly-free, all-in-one solution which handles authentication, spam prevention,
allows the site owner’s comments and replies to be displayed highlighted in the
among other commenters all without needing to worry about any maintenance.&lt;/p&gt;

&lt;p&gt;These luxuries come at a cost of &lt;strong&gt;page weight&lt;/strong&gt;, the guaranteed &lt;strong&gt;privacy&lt;/strong&gt;
of both you as the website owner and all of your users, and the &lt;strong&gt;need to login to Disqus&lt;/strong&gt;
for anyone to create a comment.&lt;/p&gt;

&lt;h3 id=&quot;response-times-with-and-without-disqus&quot;&gt;Response times with and without Disqus.&lt;/h3&gt;

&lt;p&gt;With Disqus enabled to load by default, the page-weight - also known as your 
web page’s load time - becomes a nightmare. This has implications on the SEO
of your website, the time before your web page is completely usable, the amount
of data which your users need to receive over a possible cellular connection, 
and thereby the probability that users will return to your website ever again.&lt;/p&gt;

&lt;p&gt;Without Disqus, we see an entire 800ms difference in time it takes your website
to fully render to the user. thats almost a second of time every request to your
website that gets lost in the abyss of potential seo ranking.&lt;/p&gt;

&lt;h3 id=&quot;lets-take-a-deeper-look-at-the-websites-were-requesting-here&quot;&gt;Let’s take a deeper look at the websites we’re requesting here.&lt;/h3&gt;
&lt;p&gt;Hint: it’s whole lot of tracking&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;flavio.com - tracking&lt;/li&gt;
  &lt;li&gt;google.com - the literal botnet&lt;/li&gt;
  &lt;li&gt;derp.com - more tracking&lt;/li&gt;
  &lt;li&gt;flavio2.com - virustotal scan of this website says do not trust&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;other-solutions&quot;&gt;Other solutions&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/assets/img/comments.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h3 id=&quot;third-party&quot;&gt;Third Party&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://developers.facebook.com/products/social-plugins/comments/?utm_campaign=social_plugins&amp;amp;utm_medium=offsite_pages&amp;amp;utm_source=comments_plugin&quot;&gt;Facebook comments&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Muut&lt;/li&gt;
  &lt;li&gt;Remarkbox&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;hosted-solutions&quot;&gt;Hosted Solutions&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://artsy.github.io/blog/2017/07/15/Comments-are-on/&quot;&gt;Github Comments&lt;/a&gt; (This solution is awesome too!)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;off-site-hosting&quot;&gt;Off-site hosting&lt;/h3&gt;
&lt;p&gt;When you care about your website’s performance but don’t want to miss the convenience of third-party services, you may want to outsource the comments completely. The implementation is as simple as including an external link at the end of your articles. However, data ownership remains an issue you need to evaluate.&lt;/p&gt;

&lt;p&gt;Twitter. You probably promote your articles via Twitter already. We can reverse this process. For every blog post, include a link back to your Tweet, where people can leave their comments.
Reddit. Create your own subreddit and post a link to every new blog article. As a bonus, your posts can be voted on, so you get a nice popularity overview.
Hacker News. Similar to Reddit, but aimed towards a more technical audience. However, you don’t get a dedicated space for your links.
Whether this is a viable option also depends on your reader’s demographics.&lt;/p&gt;

&lt;h3 id=&quot;no-comments&quot;&gt;No comments&lt;/h3&gt;
&lt;p&gt;I would stray from this solution personally. This depends on what environment you invision your website flourishing in of course.
In any website, comments are conducive to a community feeling as users have the ability to
interact with each other by bonding, or arguing over ideas expressed in comments.
Comments also allow ideas to be peer reviewed - a concept which inherently brings the best
ideas to fruition. I find that a blog without comments is much less
of a democracy and more of a dictatorship of ideas. The process of peer reviewing any idea brings out
the best qualities of the idea and any flaws it may have which were not covered in the article. 
As long as the reader has enough mental experience to see through ideas which are not
conducive to thoughtful conversation.&lt;/p&gt;

&lt;h2 id=&quot;my-comment-solution&quot;&gt;My comment solution&lt;/h2&gt;
&lt;p&gt;After creating &lt;a href=&quot;https://github.com/aldenjenkins/serverless-recaptcha-form&quot;&gt;my serverless contact form&lt;/a&gt;,
I was inspired to see if there were any other solutions I could implement in
my serverless backend. After doing some research, I found a
&lt;a href=&quot;&quot;&gt;great solution here&lt;/a&gt;, but didn’t feel that it had enough out-of-the-box
spam protection or abuse protection, or that It was easily deployable or updatable enough.
I decided to create my own version which now uses Google’s reCAPTCHA verification, 
and uses gravatar&lt;/p&gt;

&lt;p&gt;You can see more about &lt;a href=&quot;/blog/install-serverless-comment-system&quot;&gt;how to install a serverless comment system by following my tutorial here&lt;/a&gt;&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://aldenjenkins.com/blog/stop-using-disqus/&quot;&gt;Stop Using Disqus&lt;/a&gt; was originally published by Alden Jenkins at &lt;a href=&quot;https://aldenjenkins.com&quot;&gt;Alden Jenkins&lt;/a&gt; on October 24, 2018.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[What is a Serverless Backend?]]></title>
  <link rel="alternate" type="text/html" href="https://aldenjenkins.com/blog/what-is-a-serverless-backend/" />
  <id>https://aldenjenkins.com/blog/this-website-is-entirely-serverless</id>
  <published>2018-10-12T00:00:00-04:00</published>
  <updated>2018-10-12T00:00:00-04:00</updated>
  <author>
    <name>Alden Jenkins</name>
    <uri>https://aldenjenkins.com</uri>
  </author>
  <content type="html">&lt;h4 style=&quot;text-align: center;&quot; id=&quot;this-website-is-completely-serverless&quot;&gt;&lt;strong&gt;This website is completely serverless&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;Serverless backends are becoming the bleeding edge of web backend solutions.
The irony of a serverless backend is that there is actually still a server,
but it is unaccessible at the hardware level to both the public and you as the
web service creator. The awesome part about serverless backends is that they 
still provides the same features and dynamic content available
on a normally hosted server backend.&lt;/p&gt;

&lt;h3 id=&quot;how-is-this-possible&quot;&gt;How is this possible?&lt;/h3&gt;

&lt;p&gt;The standard deployment of a web backend involves spinning up a rented bare-metal VPS and deploying
your service onto the server and serving it to the public through a reverse-proxy like nginx or Apache.
In this standard model, you as the server renter are responsible for maintaining the
security from attacks like open ports, ensuring server uptime, and updates of the server’s operating system.
This has been the standard since the beginning of web hosting, but has never providede
the solution to the aforementioned set of security risks. Here’s where serverless backends come in.&lt;/p&gt;

&lt;p&gt;At its core, a “serverless” backend is still one that is hosted on a server,
but the server is maintained by a cloud provider like Amazon, Microsoft, or Google. &lt;strong&gt;This allows
you to forego any concerns other than the pure function of your web service.&lt;/strong&gt;
The big players simply run your functions on their servers. This coins the term
Function as a Service (FaaS).&lt;/p&gt;

&lt;p&gt;As opposed to standard bare metal hosting model where you would pay for the server and resources
on a monthly basis, serverless backends are charged based on their usage. 
This benefits the majority of websites who dont receive exorbitant amounts of traffic
to a point where the cost of renting a server for an entire month outweighs the slightly more
expensive price-per-second of FaaS running your code. For perspective, the Amazon Lambda
FaaS let’s you run 1,000,000 requests per month, or 400,000GB-Seconds of compute time per month 
before you are charged a single cent, and after that, just $0.20 per 1,000,000 requests thereafter.
This means you could get 1,000,000 contact form requests from my &lt;a href=&quot;&quot;&gt;serverless contact form application&lt;/a&gt;
before you are even charged a penny.&lt;/p&gt;

&lt;p&gt;Serverless also means you can deploy a completely static site with dynamic features.
This website includes functional mail
This website was created using the static site generator &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt;, and is hosted entirely
for free on &lt;a href=&quot;https://pages.github.com/&quot;&gt;Github Pages&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Checkout my serverless applications on &lt;a href=&quot;https://github.com/aldenjenkins&quot;&gt;my github profile!&lt;/a&gt;&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://aldenjenkins.com/blog/what-is-a-serverless-backend/&quot;&gt;What is a Serverless Backend?&lt;/a&gt; was originally published by Alden Jenkins at &lt;a href=&quot;https://aldenjenkins.com&quot;&gt;Alden Jenkins&lt;/a&gt; on October 12, 2018.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Django's bulk_update() feature is God Mode]]></title>
  <link rel="alternate" type="text/html" href="https://aldenjenkins.com/blog/django-bulk-update/" />
  <id>https://aldenjenkins.com/blog/django-bulk-update-is-god-mode</id>
  <published>2018-10-06T00:00:00-04:00</published>
  <updated>2018-10-06T00:00:00-04:00</updated>
  <author>
    <name>Alden Jenkins</name>
    <uri>https://aldenjenkins.com</uri>
  </author>
  <content type="html">&lt;p&gt;One of the most common issues I run into with Django performance is extraneous database queries. 
Whether its an &lt;a href=&quot;http://blog.scoutapp.com/articles/2018/04/30/finding-and-fixing-n-1s-in-django-apps&quot;&gt;n+1 query issue&lt;/a&gt;,
a misuse of complex Q objects, or just a misunderstanding of queryset best practices, it can be tough
to get your head around what the issue is in your case.
Django gives tons of functionality as a framework, but for most people just getting started
it’s often too much functionality to comprehend.
This post will dive into essential queryset best practices and a 
comparison of the number of queries backing them.&lt;/p&gt;

&lt;h3 id=&quot;imagine-the-following&quot;&gt;Imagine the following:&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;all_notifications&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Notification&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;notification&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;all_notifications&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;notification&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'type1'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'type2'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'type3'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;notification&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This code runs a query for each object in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all_notifications&lt;/code&gt; queryset. 
Conversely, the following code runs a single query for the entire &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all_notifications&lt;/code&gt; queryset, 
and accomplishes the same goal in:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;half the lines of code (you can even do it in one line)&lt;/li&gt;
  &lt;li&gt;literally one database query&lt;/li&gt;
  &lt;li&gt;twice the elegance&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;all_notifications&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Notification&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;all_notifications&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type__in&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'type1'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'type2'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'type3'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;What we’re doing here is a something you always want to do when given
the opportunity. &lt;strong&gt;We’re making the database do most of the work instead of Django.&lt;/strong&gt;
By filtering the queryset’s type to include all 3 types we are looking for, we
forego the need to iterate through each object in the query set to then check it’s
value. Instead, we tell our database to get the objects we want for us.&lt;/p&gt;

&lt;h3 id=&quot;see-it-in-action&quot;&gt;See it in action!&lt;/h3&gt;
&lt;figure&gt;
&lt;script src=&quot;https://asciinema.org/a/MgOTYUg7TcFSbVnub39VLNeg2.js&quot; id=&quot;asciicast-MgOTYUg7TcFSbVnub39VLNeg2&quot; async=&quot;&quot;&gt;&lt;/script&gt;
   &lt;figcaption&gt;Me using query_set.update() to save me countless queries&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;bulk_create&quot;&gt;bulk_create()&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;this one is actually a function&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;bulk_create() it something I use all the time for making notifications in metoo 
on post_save signals for certain models. For example, anytime a Rabble comment is
created, I make Notification objects for each user who the comment was replying to
in addition to the author of the post.&lt;/p&gt;

&lt;p&gt;bulk_create() works much like the query_set.update() in that it drastically
reduces the number of queries that Django gives the database in contrast to
the per-object amount you would run in the most pragmatic university-educated
programmer style.&lt;/p&gt;

&lt;h3 id=&quot;bad-implementation&quot;&gt;Bad implementation&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;replied_to_users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;Notification&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;comment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;the_comment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;RepliedToRabble&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Don’t be fooled by the low line count here! This implementation runs a SQL query for each
user in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;replied_to_users&lt;/code&gt;. Imagine if the number of Notification objects you were creating here
was 100 or 100000! Considering an average query response from your database to Django takes ~25ms,
you’re looking at some serious lag time. Let’s see a more elegant and efficient implementation.&lt;/p&gt;

&lt;h3 id=&quot;single-query&quot;&gt;Single query&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;new_notifications&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;replied_to_users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;new_notifications&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Notification&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;comment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;the_comment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;RepliedToRabble&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Notification&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bulk_create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_notifications&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Taking the time to consider how you may be running unnecessary queries in your
projects and reap the rewards of speed!&lt;/p&gt;


  &lt;p&gt;&lt;a href=&quot;https://aldenjenkins.com/blog/django-bulk-update/&quot;&gt;Django's bulk_update() feature is God Mode&lt;/a&gt; was originally published by Alden Jenkins at &lt;a href=&quot;https://aldenjenkins.com&quot;&gt;Alden Jenkins&lt;/a&gt; on October 06, 2018.&lt;/p&gt;</content>
</entry>

</feed>
