<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: ✨iMichael✨</title>
    <description>The latest articles on Forem by ✨iMichael✨ (@imichael).</description>
    <link>https://forem.com/imichael</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F89074%2Fcbcb6306-97c9-4405-a649-c19e0f6a2822.jpeg</url>
      <title>Forem: ✨iMichael✨</title>
      <link>https://forem.com/imichael</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/imichael"/>
    <language>en</language>
    <item>
      <title>Introducing PipFlow</title>
      <dc:creator>✨iMichael✨</dc:creator>
      <pubDate>Sat, 11 Jan 2020 19:37:14 +0000</pubDate>
      <link>https://forem.com/imichael/introducing-pipflow-5e3d</link>
      <guid>https://forem.com/imichael/introducing-pipflow-5e3d</guid>
      <description>&lt;p&gt;I recently published a new Python package manager called &lt;a href="https://pypi.org/project/Pipflow/"&gt;PipFlow&lt;/a&gt;. If you're like me and use Docker for everything (local development + containers in production), you might like it.&lt;/p&gt;

&lt;p&gt;Let's take a step back and dive into what problem it solves and at the end I'll tell you why the newer package managers were not a good fit for me. Here are my priors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I believe in making my local development mirror production NOT make production mirror my local development.&lt;/li&gt;
&lt;li&gt;Therefore I do everything in Docker (and k8s)&lt;/li&gt;
&lt;li&gt;In Docker, the slimmer the image the better. Also if you can avoid redundant dependencies and build steps, you should.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With that out of the way, let's add some new packages. Requests is cool –– let's install it the old way.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install requests
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I now have this package in my host operating system, but it's useless there because I use docker locally. So let's get the package and add it to my &lt;code&gt;requirements.txt&lt;/code&gt; file.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip freeze | grep requests &amp;gt;&amp;gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;My requirements now has &lt;code&gt;requests==2.22.0&lt;/code&gt; in it. Okay cool, but now we need to rebuild our docker image to bake in the new dependency&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose build app
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Everything works great now, but let's take a moment to identify some waste: I just installed a package twice to use it. There must be a better way, right? There is:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pipflow add requests
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The command above gets the latest requests version and adds it to our requirements file, sorts the file, and rebuilds the docker image – which is the only installation step that matters. The great thing is that we don't need to install pipflow in our Dockerfile, just once in our host operating system. &lt;/p&gt;

&lt;p&gt;Pipflow is really a "pip workflow" that just simplifies a few steps into one step. Inspired by the &lt;a href="https://yarnpkg.com/lang/en/"&gt;yarn&lt;/a&gt; command line API, pipflow also does upgrades for single packages &lt;code&gt;pipflow upgrade &amp;lt;package&amp;gt;&lt;/code&gt; and removes packages with &lt;code&gt;pipflow remove &amp;lt;package&amp;gt;&lt;/code&gt;. You can also upgrade all packages with &lt;code&gt;pipflow upgrade-all&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So why don't I use one of these newer tools like Poetry or Pipenv? The answer is that these tools solve problems that don't exist in Docker.&lt;/p&gt;

&lt;p&gt;Lets read the &lt;a href="https://github.com/pypa/pipenv"&gt;pipenv README&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You no longer need to use pip and virtualenv separately. They work together&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Virtual Environments are not necessary in Docker – Docker already has isolation and sandboxing. Next time you do &lt;code&gt;ADD venv .&lt;/code&gt; in Docker, ask yourself what problem you're solving.&lt;/p&gt;

&lt;p&gt;What about Poetry and other tools that use lock files, those are useful aren't they? &lt;/p&gt;

&lt;p&gt;Nothing is gained by using a secondary lock file in Docker. Requirements txt files are perfectly fine at pinning versions (requirements.txt is your manifest + lockfile already). In fact there is a loss: You have to generate the lock file AND/OR you have to install the tool in your Docker image. Both are wasteful, redundant build steps.&lt;/p&gt;

&lt;p&gt;Another thing to remember is that when you do &lt;code&gt;RUN pip install -r requirements.txt&lt;/code&gt; in Docker, a new image layer is created – this layer represents all the new packages added to the file system and each layer gets a unique sha256 digest (in effect a lock file mechanism). If you build again and nothing changed in your requirements, the layer is cached. It's a beautiful thing.&lt;/p&gt;

&lt;p&gt;Here's what my Dockerfile looks like in a production project that uses pipflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM python:3.8.0-alpine

EXPOSE 8000

WORKDIR /app

RUN addgroup -S app &amp;amp;&amp;amp; adduser -S -G app app

ADD requirements.txt .

RUN pip install -r requirements.txt

ADD . .

USER app

ENTRYPOINT ["scripts/entrypoint.sh"]

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can find the repo on &lt;a href="https://github.com/iMerica/pipflow"&gt;Github&lt;/a&gt; and the PyPi package &lt;a href="https://pypi.org/project/Pipflow/"&gt;here&lt;/a&gt; or just install it with &lt;code&gt;pip install pipflow&lt;/code&gt;. The only assumptions are: your Dockerfile/image has &lt;code&gt;pip&lt;/code&gt; installed and you have these two lines in your Dockerfile (ideally before you add the rest of the source code for optimal caching).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ADD requirements.txt .

RUN pip install -r requirements.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let me know if you love it, hate it, or  &lt;code&gt;¯\_(ツ)_/¯&lt;/code&gt;. It's a young project, so expect a few kinks 😃.&lt;/p&gt;

</description>
      <category>python</category>
      <category>docker</category>
      <category>showdev</category>
      <category>packagemanager</category>
    </item>
    <item>
      <title>Continuously Deploy Your Frontend using Gitlab and Scotty.JS </title>
      <dc:creator>✨iMichael✨</dc:creator>
      <pubDate>Sun, 05 Aug 2018 07:43:30 +0000</pubDate>
      <link>https://forem.com/imichael/continuously-deploy-your-frontend-using-gitlab-and-scottyjs--15j8</link>
      <guid>https://forem.com/imichael/continuously-deploy-your-frontend-using-gitlab-and-scottyjs--15j8</guid>
      <description>&lt;p&gt;My lovefest for &lt;a href="https://gitlab.com/"&gt;Gitlab&lt;/a&gt; continues! Heres a quick post showing you how to continuously deploy your React/Vue/Angular Single Page Applications to S3 and Cloudfront, using just Docker, Gitlab and great tool called &lt;a href="https://github.com/stojanovic/scottyjs"&gt;Scotty.JS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First save &lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt; and &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt; to your Gitlab environment variables (I recommend a special IAM role for this). Then save the files below to your repository and update the placeholder text to what makes sense for your project.&lt;/p&gt;

&lt;p&gt;The Dockerfile below performs a multi-stage build that builds the frontend code (Create-React-App) then copies all of it to a directory that Scotty can access.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;#Dockerfile&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:8.11.3-slim as node_builder&lt;/span&gt;

&lt;span class="k"&gt;MAINTAINER&lt;/span&gt;&lt;span class="s"&gt; @iMichael&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; /src  /app/src&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /app/src &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    npm run build

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:8.11.3-slim as deployer&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;groupadd &lt;span class="nt"&gt;-r&lt;/span&gt; react &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; useradd &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; react react

&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;scottyjs &lt;span class="nt"&gt;--global&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=node_builder /app/src/build /tmp/build&lt;/span&gt;

&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; react&lt;/span&gt;

&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["scotty"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And below is the Gitlab config that ties it all together. Update this with any special logic your team adheres to (like only deploying if all tests pass on the master branch).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;#.gitlab-ci.yml&lt;/span&gt;
&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker:latest&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker:dind&lt;/span&gt;

&lt;span class="na"&gt;stages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;push&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;deploy&lt;/span&gt;

&lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;REACT_TAG_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;registry.gitlab.com/&amp;lt;user&amp;gt;/&amp;lt;project&amp;gt;/&amp;lt;container-name&amp;gt;:$CI_COMMIT_REF_NAME&lt;/span&gt;
  &lt;span class="na"&gt;S3_BUCKET&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;xxxx&lt;/span&gt;

&lt;span class="na"&gt;before_script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.gitlab.com&lt;/span&gt;

&lt;span class="s"&gt;build:react:&lt;/span&gt;
  &lt;span class="s"&gt;artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker-images&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mkdir docker-images&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker build --pull -t $REACT_TAG_NAME -f path/to/your/Dockerfile .&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker save $REACT_TAG_NAME &amp;gt; docker-images/react.tar&lt;/span&gt;

&lt;span class="s"&gt;push:react:&lt;/span&gt;
  &lt;span class="s"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;push&lt;/span&gt;
  &lt;span class="s"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker load -i docker-images/react.tar&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker push $REACT_TAG_NAME&lt;/span&gt;
  &lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;

&lt;span class="s"&gt;deploy:react:&lt;/span&gt;
  &lt;span class="s"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy&lt;/span&gt;
  &lt;span class="s"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker run \&lt;/span&gt;
      &lt;span class="s"&gt;--rm  \&lt;/span&gt;
      &lt;span class="s"&gt;-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \&lt;/span&gt;
      &lt;span class="s"&gt;-e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY  \&lt;/span&gt;
      &lt;span class="s"&gt;$REACT_TAG_NAME  \&lt;/span&gt;
      &lt;span class="s"&gt;--source /tmp/build/ \&lt;/span&gt;
      &lt;span class="s"&gt;--region us-east-1 \&lt;/span&gt;
      &lt;span class="s"&gt;--bucket $S3_BUCKET \&lt;/span&gt;
      &lt;span class="s"&gt;--spa&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now every time you push to master on Gitlab (and all tests pass). your code will be deployed to AWS with a Cloudfront URL that you can CNAME to your own domain. &lt;/p&gt;

&lt;p&gt;Big thanks to Scotty.js which does all the heavy lifting!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>devops</category>
    </item>
    <item>
      <title>A framework for choosing from multiple job offers.</title>
      <dc:creator>✨iMichael✨</dc:creator>
      <pubDate>Fri, 03 Aug 2018 08:20:52 +0000</pubDate>
      <link>https://forem.com/imichael/a-framework-for-choosing-from-multiple-job-offers-476n</link>
      <guid>https://forem.com/imichael/a-framework-for-choosing-from-multiple-job-offers-476n</guid>
      <description>&lt;p&gt;"Which job offer should I accept" is a question I see pretty frequently in various Slack groups and hear IRL. The answer of course is always personal and subjective so I thought it would be helpful to write software that helps organize our thoughts in a structured way and eliminate the &lt;a href="https://en.wikipedia.org/wiki/Decision_fatigue"&gt;Decision Fatigue&lt;/a&gt; associated with multiple good options.&lt;/p&gt;

&lt;p&gt;I've published a very alpha quality version in Python-3.7 @ &lt;a href="https://github.com/iMerica/job-offer-selector"&gt;https://github.com/iMerica/job-offer-selector&lt;/a&gt;. Feel free to fork it or use it as inspiration.&lt;/p&gt;

&lt;p&gt;The core idea here is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rank the categories that are most important to you.&lt;/li&gt;
&lt;li&gt;Rank the companies in these categories.&lt;/li&gt;
&lt;li&gt;Select the company that performs best using a weighted average.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;P.S. Python 3.7's new data class module is pretty awesome. This project relies upon them pretty heavily.&lt;/p&gt;

</description>
      <category>python</category>
      <category>career</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Automagically build and push Docker images to a registry using Gitlab.</title>
      <dc:creator>✨iMichael✨</dc:creator>
      <pubDate>Fri, 03 Aug 2018 07:57:37 +0000</pubDate>
      <link>https://forem.com/imichael/automagically-build-and-push-docker-images-to-a-registry-using-gitlab-276p</link>
      <guid>https://forem.com/imichael/automagically-build-and-push-docker-images-to-a-registry-using-gitlab-276p</guid>
      <description>&lt;p&gt;This is an example configuration for how to automatically build Docker images and push to your own Docker registry on Gitlab (free). In this example, I'm building and testing a Docker image that runs Django, but the same basic idea will work for any app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker:latest&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker:dind&lt;/span&gt;

&lt;span class="na"&gt;stages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;push&lt;/span&gt;

&lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;DJANGO_TAG_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;registry.gitlab.com/&amp;lt;username&amp;gt;/&amp;lt;repo&amp;gt;/&amp;lt;image&amp;gt;:$CI_COMMIT_REF_NAME&lt;/span&gt;
  &lt;span class="na"&gt;DJANGO_SETTINGS_MODULE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;path.to.your.settings&lt;/span&gt;
  &lt;span class="na"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres://postgres:xxxxxxx@postgres/postgres&lt;/span&gt;

&lt;span class="na"&gt;before_script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.gitlab.com&lt;/span&gt;

&lt;span class="s"&gt;build:django:&lt;/span&gt;
  &lt;span class="s"&gt;artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker-images&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mkdir docker-images&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker build --pull -t $DJANGO_TAG_NAME -f path/to/your/Dockerfile .&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker save $DJANGO_TAG_NAME &amp;gt; docker-images/app.tar&lt;/span&gt;
  &lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;
&lt;span class="s"&gt;test:django:&lt;/span&gt;
  &lt;span class="s"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
  &lt;span class="s"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker load -i docker-images/app.tar&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker run --name test-postgres -e POSTGRES_PASSWORD=xxxxxxx -d postgres&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker run --rm --link test-postgres:postgres -v $(pwd):/&amp;lt;DOCKER WORKDIR&amp;gt; -e DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE -e DATABASE_URL=$DATABASE_URL $DJANGO_TAG_NAME python manage.py test -v &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;

&lt;span class="s"&gt;push:django:&lt;/span&gt;
  &lt;span class="s"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;push&lt;/span&gt;
  &lt;span class="s"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker load -i docker-images/app.tar&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker push $DJANGO_TAG_NAME&lt;/span&gt;
  &lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>docker</category>
      <category>devops</category>
      <category>ci</category>
    </item>
    <item>
      <title>This one trick gives you unlimited CI minutes on Gitlab.</title>
      <dc:creator>✨iMichael✨</dc:creator>
      <pubDate>Fri, 03 Aug 2018 07:49:04 +0000</pubDate>
      <link>https://forem.com/imichael/this-one-trick-gives-you-unlimited-ci-minutes-on-gitlab-e92</link>
      <guid>https://forem.com/imichael/this-one-trick-gives-you-unlimited-ci-minutes-on-gitlab-e92</guid>
      <description>&lt;p&gt;Gitlab graciously provides 2,000 free minutes per month to all users on Gitlab.com (thanks Gitlab!). I deploy many times a day so it's quite easy to use all 2K minutes in a matter of days. &lt;/p&gt;

&lt;p&gt;Here is how to get around that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spin up a new compute instance with Docker pre-installed. I recommend &lt;a href="https://m.do.co/c/f1de666e40fd"&gt;Digital Ocean&lt;/a&gt;, but &lt;a href="https://www.vultr.com/?ref=7495712"&gt;Vultr&lt;/a&gt; is pretty good too.&lt;/li&gt;
&lt;li&gt;Replace the &lt;code&gt;CI_SERVER_URL&lt;/code&gt; value with one from your actual server URL. Go to the CI settings for your project and get your registration token under the "Runners" section. Then update &lt;code&gt;REGISTRATION_TOKEN&lt;/code&gt; in the yml file.&lt;/li&gt;
&lt;li&gt;Ssh into your server and save the code below to a file called &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;docker-compose up -d&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2'&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;dind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;privileged&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/var/lib/docker&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker:18.06.0-ce-dind&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--storage-driver=overlay2&lt;/span&gt;

  &lt;span class="na"&gt;runner&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gitlab/gitlab-runner:alpine&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./gitlab/runner:/etc/gitlab-runner:Z&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DOCKER_HOST=tcp://dind:2375&lt;/span&gt;

  &lt;span class="na"&gt;register-runner&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;no'&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gitlab/gitlab-runner:alpine&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./gitlab/runner:/etc/gitlab-runner:Z&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;register&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--non-interactived&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--locked=false&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--name=Docker Runner&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--executor=docker&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--docker-image=docker:18.06.0-ce-dind&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--docker-volumes=/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CI_SERVER_URL=https://XXXXXXXX.XXXXX&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;REGISTRATION_TOKEN=XXXXXXX&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>docker</category>
      <category>devops</category>
      <category>testing</category>
      <category>ci</category>
    </item>
  </channel>
</rss>
