<?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: Dongchao (Alan) Chen</title>
    <description>The latest articles on Forem by Dongchao (Alan) Chen (@dongchaochen).</description>
    <link>https://forem.com/dongchaochen</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%2F347300%2F0c0d9df1-f98d-4735-a568-be3a498b898a.png</url>
      <title>Forem: Dongchao (Alan) Chen</title>
      <link>https://forem.com/dongchaochen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dongchaochen"/>
    <language>en</language>
    <item>
      <title>Upgrade old docker-compose in Ubuntu 18.04</title>
      <dc:creator>Dongchao (Alan) Chen</dc:creator>
      <pubDate>Thu, 25 Nov 2021 02:54:06 +0000</pubDate>
      <link>https://forem.com/dongchaochen/upgrade-old-docker-compose-in-ubuntu-1804-2mkn</link>
      <guid>https://forem.com/dongchaochen/upgrade-old-docker-compose-in-ubuntu-1804-2mkn</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;I am in an old system which installed Ubuntu 18.04, it has specifc security rules that does not allow user to talk to outside network, and I had issue using old version &lt;code&gt;docker-compose&lt;/code&gt; which got installed by &lt;code&gt;sudo apt install docker-compose&lt;/code&gt;. But I really need the latest &lt;code&gt;docker-compose&lt;/code&gt; from github so that can support my latest docker-compose.yml definitions.&lt;/p&gt;

&lt;h2&gt;
  
  
  With Network Access
&lt;/h2&gt;

&lt;p&gt;My favourite way when there is network access to github.com is always as described in this &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-compose-on-ubuntu-20-04"&gt;article&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

sudo chmod +x /usr/local/bin/docker-compose

docker-compose --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But how about no network?&lt;/p&gt;

&lt;h2&gt;
  
  
  No Network Access
&lt;/h2&gt;

&lt;p&gt;Luckily that old Ubuntu 18.04 system, I can manage to upload &lt;code&gt;docker-compose&lt;/code&gt; file I downloaded from other machine and then I did&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo cp docker-compose /usr/local/bin/docker-compose

sudo chmod +x /usr/local/bin/docker-compose

docker-compose --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you thought it will work, right? &lt;/p&gt;

&lt;p&gt;But you got this error message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose: error while loading shared libraries: libz.so.1: failed to map segment from shared object
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Soluton is do the following command, see some explain &lt;a href="https://stackoverflow.com/questions/57796839/docker-compose-error-while-loading-shared-libraries-libz-so-1-failed-to-map-s/58068483"&gt;here&lt;/a&gt; - "resolved by re-mounting the /tmp to give the volume permission to execute, it was accessible with read-only"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mount /tmp -o remount,exec
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you will have the latest &lt;code&gt;docker-compose&lt;/code&gt; on your old Ubuntu 18.04.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
    </item>
    <item>
      <title>move /var/lib/docker to different volume for docker images</title>
      <dc:creator>Dongchao (Alan) Chen</dc:creator>
      <pubDate>Thu, 14 Oct 2021 02:29:56 +0000</pubDate>
      <link>https://forem.com/dongchaochen/move-varlibdocker-to-different-volume-for-docker-images-54</link>
      <guid>https://forem.com/dongchaochen/move-varlibdocker-to-different-volume-for-docker-images-54</guid>
      <description>&lt;h2&gt;
  
  
  Problem 1 - need move &lt;code&gt;/var/lib/docker&lt;/code&gt; to large volume
&lt;/h2&gt;

&lt;p&gt;Our local linux disk volume is under &lt;strong&gt;30GB&lt;/strong&gt;, so it will be quite challenge for our docker images, which take a lot of space under &lt;code&gt;/var/lib/docker&lt;/code&gt; folder and quickly run out of space. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh22d28hjzc75fywzgcd5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh22d28hjzc75fywzgcd5.png" alt="small disk size"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Solution for Problem 1
&lt;/h2&gt;

&lt;p&gt;It is possible to follow this artile - &lt;a href="https://medium.com/clusterfk/use-a-different-volume-for-your-docker-images-in-ubuntu-4c0315be6d66" rel="noopener noreferrer"&gt;Use a Different Volume For Your Docker Images in Ubuntu&lt;/a&gt; that mount a new volume folder e.g. &lt;code&gt;/dev/sda2&lt;/code&gt; for &lt;code&gt;/var/lib/docker&lt;/code&gt; and add the following line&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/dev/sda2    /var/lib/docker    ext4    defaults    0    1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in &lt;code&gt;/etc/fstab&lt;/code&gt; so the mount also happen during startup linux.&lt;/p&gt;

&lt;p&gt;A quick tip to get volume type is using command &lt;code&gt;df -T&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxxgdv498m6iat88jki9o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxxgdv498m6iat88jki9o.png" alt="use command df -T"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What I did in fact follow this artile - &lt;a href="https://www.guguweb.com/2019/02/07/how-to-move-docker-data-directory-to-another-location-on-ubuntu/" rel="noopener noreferrer"&gt;How to move docker data directory to another loccation on Ubuntu&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stop the docker daemon
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo service docker stop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and make sure that docker is not running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ps faux | grep -i docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;make the folder and &lt;code&gt;rsync&lt;/code&gt; the files
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mkdir /mnt/docker
$ rsync -avxP /var/lib/docker/ /mnt/docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Update docker configuration

&lt;ul&gt;
&lt;li&gt;Add a configuration file and tell the docker daemon what is the location of the data directory by creating a file called &lt;code&gt;daemon.json&lt;/code&gt; under directory &lt;code&gt;/etc/docker&lt;/code&gt;. the file should have the content:
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "data-root":"/mnt/docker"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Update the docker service by editing &lt;code&gt;/lib/systemd/system/docker.service&lt;/code&gt;
Find the following line
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and update to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ExecStart=/usr/bin/dockerd -g /mnt/docker -H fd:// --containerd=/run/containerd/containerd.sock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Re-start the docker daemon
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo service docker start
# reload docker serivce configuration 
sudo systemctl daemon-reload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;test by the following command after you pull an image
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker inspect image_id | grep WorkDir
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Problem 2 - After linux reboot, docker images are gone
&lt;/h2&gt;

&lt;p&gt;The docker images under &lt;code&gt;/mnt/docker&lt;/code&gt; are gone, e.g. &lt;code&gt;/mnt/docker/overlay2&lt;/code&gt; has no docker images that we pulled fromm DockerHub. &lt;/p&gt;

&lt;p&gt;See github discussion &lt;a href="https://github.com/moby/moby/issues/36149" rel="noopener noreferrer"&gt;https://github.com/moby/moby/issues/36149&lt;/a&gt;&lt;br&gt;
and PR &lt;a href="https://github.com/moby/sys/pull/62" rel="noopener noreferrer"&gt;https://github.com/moby/sys/pull/62&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution for Problem 2
&lt;/h2&gt;

&lt;p&gt;No solution yet, keep looking! So far, have to re-pull the docker images.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
    </item>
    <item>
      <title>Google Nexus 5 reload image</title>
      <dc:creator>Dongchao (Alan) Chen</dc:creator>
      <pubDate>Thu, 11 Feb 2021 04:33:26 +0000</pubDate>
      <link>https://forem.com/dongchaochen/google-nexus-5-reload-image-40ol</link>
      <guid>https://forem.com/dongchaochen/google-nexus-5-reload-image-40ol</guid>
      <description>&lt;h1&gt;
  
  
  Why I did upgrade?
&lt;/h1&gt;

&lt;p&gt;My 2 years old daughter was around me and was looking for some nice toy, she does not want to play with any existing toys now. Ok, I gave her my very old Google Nexus 5, she liked it and she used it to pretend to make phone calls and taking pictures. The world is calm and I can back to write some code now. &lt;/p&gt;

&lt;p&gt;After supper, I checked that Nexus 5, need more power charge and maybe the system is too old, as a programmer who sometimes considers too much about security, the first step is upgrading it, so I did the upgrade. &lt;/p&gt;

&lt;p&gt;It is 2021 now, and the phone quickly taught your lesson you should not do the upgrade instead you should just throw it away since it is too old! But my little girl still want to play it and now I just made it totally un-function. &lt;/p&gt;

&lt;h1&gt;
  
  
  How about reset
&lt;/h1&gt;

&lt;p&gt;Reset back to factory image is the first step I tried, follow some link like &lt;a href="https://www.verizon.com/support/knowledge-base-208003/"&gt;Factory Data Reset&lt;/a&gt;. Still failed since the factory image was corrupted, now I am in real trouble. &lt;/p&gt;

&lt;h1&gt;
  
  
  Solution
&lt;/h1&gt;

&lt;p&gt;Some old Android programming knowledge told me that I should just take a look maybe I can get some help from Android website, so yes, I found the Factory Image from Android &lt;a href="https://developers.google.com/android/images"&gt;webpage&lt;/a&gt;. I quickly downloaded the Android Studio to start re-program the phone, and failed again with ADB Fastboot error.&lt;/p&gt;

&lt;p&gt;Thanks to Stackoverflow found the solution that I need older version of Android platform-tools. After installed the older version of platform tool, Finally, I got the factory image loaded back to phone and it is working again. &lt;/p&gt;

&lt;h1&gt;
  
  
  References for StackOverflow
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/60443933/adb-fastboot-error-when-flasing-rom-failed-remote-unknown-command"&gt;https://stackoverflow.com/questions/60443933/adb-fastboot-error-when-flasing-rom-failed-remote-unknown-command&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/53453640/is-there-a-way-to-install-an-older-version-of-android-platform-tools"&gt;https://stackoverflow.com/questions/53453640/is-there-a-way-to-install-an-older-version-of-android-platform-tools&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>android</category>
    </item>
    <item>
      <title>Dockerfile SHELL bite me</title>
      <dc:creator>Dongchao (Alan) Chen</dc:creator>
      <pubDate>Thu, 11 Feb 2021 04:08:07 +0000</pubDate>
      <link>https://forem.com/dongchaochen/dockerfile-shell-bite-me-47k3</link>
      <guid>https://forem.com/dongchaochen/dockerfile-shell-bite-me-47k3</guid>
      <description>&lt;h1&gt;
  
  
  Background and Problem
&lt;/h1&gt;

&lt;p&gt;I built our team's own version RStudio docker image to support any additional R / Python packages we need for internal usage that based on nice community work &lt;a href="https://github.com/rocker-org/rocker-versioned/tree/master/rstudio"&gt;rocker/rstudio&lt;/a&gt;, it has some limitation, for example, not support GPU, of course, to solve that, I borrowed the idea from Nvidia's &lt;a href="https://gitlab.com/nvidia/container-images/cuda/-/blob/master/dist/10.1/ubuntu18.04-x86_64/base/Dockerfile"&gt;Dockerfile&lt;/a&gt;, which in general added all basic CUDA libraries for you until I hit the issue to support Tenforflow GPU usage. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.tensorflow.org/install/gpu"&gt;Tensorflow GPU&lt;/a&gt; gives you details for what you need to do for Ubuntu 18.04&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Add NVIDIA package repositories
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-ubuntu1804.pin
sudo mv cuda-ubuntu1804.pin /etc/apt/preferences.d/cuda-repository-pin-600
sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub
sudo add-apt-repository "deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/ /"
sudo apt-get update

wget http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64/nvidia-machine-learning-repo-ubuntu1804_1.0.0-1_amd64.deb

sudo apt install ./nvidia-machine-learning-repo-ubuntu1804_1.0.0-1_amd64.deb
sudo apt-get update

# Install NVIDIA driver
sudo apt-get install --no-install-recommends nvidia-driver-450
# Reboot. Check that GPUs are visible using the command: nvidia-smi

wget https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64/libnvinfer7_7.1.3-1+cuda11.0_amd64.deb
sudo apt install ./libnvinfer7_7.1.3-1+cuda11.0_amd64.deb
sudo apt-get update

# Install development and runtime libraries (~4GB)
sudo apt-get install --no-install-recommends \
    cuda-11-0 \
    libcudnn8=8.0.4.30-1+cuda11.0  \
    libcudnn8-dev=8.0.4.30-1+cuda11.0


# Install TensorRT. Requires that libcudnn8 is installed above.
sudo apt-get install -y --no-install-recommends libnvinfer7=7.1.3-1+cuda11.0 \
    libnvinfer-dev=7.1.3-1+cuda11.0 \
    libnvinfer-plugin7=7.1.3-1+cuda11.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wow, doing that is crazy for my current dockerfile build regardless of whether you use the kind of multi-stage solution or not, the size is just huge and had difficult to install on top of my existing RStudio image, I decided to take a look at what Tensorflow gpu docker did. A quick look at &lt;a href="https://github.com/tensorflow/tensorflow/blob/master/tensorflow/tools/dockerfiles/dockerfiles/gpu.Dockerfile"&gt;Tensorflow gpu.Dockerfile&lt;/a&gt; makes me decided to use its logic to get all CUDA libraries / runtime install except Python part since we will install our own python version in RStudio image. &lt;/p&gt;

&lt;p&gt;So now the solution become &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use some part of Tensorflow &lt;code&gt;gpu.Dockerfile&lt;/code&gt; and build a good base image &lt;/li&gt;
&lt;li&gt;On top of that base image, we install the R version we want and then use
&lt;a href="https://github.com/rocker-org/rocker-versioned/tree/master/rstudio"&gt;rocker/rstudio&lt;/a&gt; logic to install RStudio. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything looks great and got successfully built except that now my R environment in the new build docker image does not right with additional odd character, which caused by these lines of my dockerfile&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;amp;&amp;amp; echo '\n\
      \n# Configure httr to perform out-of-band authentication if HTTR_LOCALHOST \
      \n# is not set since a redirect to localhost may not work depending upon \
      \n# where this Docker container is running. \
      \nif(is.na(Sys.getenv("HTTR_LOCALHOST", unset=NA))) { \
      \n  options(httr_oob_default = TRUE) \
      \n}' &amp;gt;&amp;gt; /usr/lib/R/etc/Rprofile.site \
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why is that, I used it so many times to build our RStudio docker image. &lt;/p&gt;

&lt;h1&gt;
  
  
  Why?
&lt;/h1&gt;

&lt;p&gt;It is caused by &lt;code&gt;SHELL ["/bin/bash", "-c"]&lt;/code&gt; that I borrowed the logic from &lt;a href="https://github.com/tensorflow/tensorflow/blob/master/tensorflow/tools/dockerfiles/dockerfiles/gpu.Dockerfile"&gt;Tensorflow gpu.Dockerfile&lt;/a&gt; now the Dockerfile build shell changed to use &lt;strong&gt;bash&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Solution
&lt;/h1&gt;

&lt;p&gt;Change back to use &lt;strong&gt;sh&lt;/strong&gt; when I continue build my RStudio part in dockerfile&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# change back to sh due to base image was using bash
SHELL ["/bin/sh", "-c"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now everything is working!&lt;/p&gt;

</description>
      <category>dockerfile</category>
    </item>
    <item>
      <title>iTerm2 start with complete:13: command not found</title>
      <dc:creator>Dongchao (Alan) Chen</dc:creator>
      <pubDate>Wed, 08 Apr 2020 21:07:32 +0000</pubDate>
      <link>https://forem.com/dongchaochen/iterm2-start-with-complete-13-command-not-found-45mf</link>
      <guid>https://forem.com/dongchaochen/iterm2-start-with-complete-13-command-not-found-45mf</guid>
      <description>&lt;p&gt;Recently when I open my &lt;a href="https://www.iterm2.com/downloads.html"&gt;iTerm2&lt;/a&gt;, I got the message &lt;code&gt;complete:13: command not found: compdef&lt;/code&gt;, where it is coming from?&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mk144aBQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k98tj6nbaunfrvj90nva.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mk144aBQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k98tj6nbaunfrvj90nva.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After some research, the answer is in my &lt;code&gt;~/.zshrc&lt;/code&gt;&lt;br&gt;
these two lines are added when I recently re-install nodejs using &lt;a href="https://github.com/nvm-sh/nvm"&gt;nvm&lt;/a&gt;, you can find this info from &lt;a href="https://github.com/nvm-sh/nvm/blob/master/README.md#git-install"&gt;nvm readme - Git install section&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mk144aBQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k98tj6nbaunfrvj90nva.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mk144aBQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k98tj6nbaunfrvj90nva.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
But it is in zsh, so no need to load &lt;strong&gt;nvm bash_completion&lt;/strong&gt;, comment out the line &lt;code&gt;[-s "$NVM_DIR/bash_completion" ] &amp;amp;&amp;amp; \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion&lt;/code&gt; will solve the problem. &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hqLSuKWW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hklqh9qwy9z8xpvw9b4w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hqLSuKWW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hklqh9qwy9z8xpvw9b4w.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Now re-open a new session, error message is gone. &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x4JermuD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1054i34jlu8oc82g7hy8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x4JermuD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1054i34jlu8oc82g7hy8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>iterm2</category>
    </item>
    <item>
      <title>What I learned from python app distribution</title>
      <dc:creator>Dongchao (Alan) Chen</dc:creator>
      <pubDate>Sat, 07 Mar 2020 14:44:37 +0000</pubDate>
      <link>https://forem.com/dongchaochen/what-i-learned-from-python-app-distribution-5h96</link>
      <guid>https://forem.com/dongchaochen/what-i-learned-from-python-app-distribution-5h96</guid>
      <description>&lt;h3&gt;
  
  
  Problem
&lt;/h3&gt;

&lt;p&gt;Recently, we need to distribute our python Flask application in docker container. Initially, I was using &lt;a href="https://github.com/ofek/hatch"&gt;hatch&lt;/a&gt; to build/test our application, by default, &lt;a href="https://github.com/ofek/hatch/blob/master/COMMANDS.rst#build"&gt;hatch build&lt;/a&gt; will produce a source distribution and a wheel. But we do not want to distribute our source code in our docker container, how can we protect our intellectual property?&lt;/p&gt;

&lt;h3&gt;
  
  
  Possible Options and Challenges
&lt;/h3&gt;

&lt;p&gt;Here are a few options that discussed in python wiki - &lt;a href="https://wiki.python.org/moin/Asking%20for%20Help/How%20do%20you%20protect%20Python%20source%20code%3F"&gt;How do you protect Python source code?&lt;/a&gt;, in summary, you have the following options&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use compiled bytecode 

&lt;ul&gt;
&lt;li&gt;The generated &lt;strong&gt;.pyc&lt;/strong&gt; files are not portable between different versions of Python &lt;/li&gt;
&lt;li&gt;You can still decompyle the &lt;strong&gt;pyc&lt;/strong&gt; file to reverse engineering.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Executable creators (or Installers)

&lt;ul&gt;
&lt;li&gt;Option like using &lt;a href="http://www.pyinstaller.org/"&gt;PyInstaller&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;But &lt;a href="http://www.pyinstaller.org/"&gt;PyInstaller&lt;/a&gt; currently not support Python 3.8 yet&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Software as a Service 

&lt;ul&gt;
&lt;li&gt;Deploy the way like Google did.&lt;/li&gt;
&lt;li&gt;deployment only on locked down VMs (client only has API acces, no console access to host).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Python Source Code Obfuscators 

&lt;ul&gt;
&lt;li&gt;Use the tool like &lt;a href="https://wiki.python.org/moin/Pyarmor"&gt;Pyarmor&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;But I am worried about the performance&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Use of modified docker container that has no shell environment or other mechanisms to prevent access to the files within docker container.

&lt;ul&gt;
&lt;li&gt;no shell in docker looks so challenge since we need bash to execute the program, allocate job tasks, etc.&lt;/li&gt;
&lt;li&gt;lock file permissions may be possible&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Besides the source code, when you build a distribution package, you can use &lt;a href="https://packaging.python.org/glossary/#term-wheel"&gt;wheel&lt;/a&gt; or &lt;a href="https://packaging.python.org/glossary/#term-egg"&gt;egg&lt;/a&gt; format, here is a good summary of &lt;a href="https://packaging.python.org/discussions/wheel-vs-egg/"&gt;Wheel vs Egg&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;When you use &lt;code&gt;$ python setup.py bdist_egg --exclude-source-files&lt;/code&gt; can help you remove source files in the distributed package, but egg file you need to use &lt;a href="https://setuptools.readthedocs.io/en/latest/easy_install.html"&gt;easy_install&lt;/a&gt; to install, which is deprecated in setuptools now, the recommended way is using &lt;strong&gt;pip&lt;/strong&gt; which need to install wheel file.&lt;/li&gt;
&lt;li&gt;thanks to stackoverflow answer - &lt;a href="https://stackoverflow.com/questions/47174664/how-to-exclude-source-code-from-bdist-wheel-python"&gt;how to exclude source code from beist_wheel python&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python setup.py bdist_egg --exclude-source-files
wheel convert dist/package-*.egg -d dist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which will generate &lt;code&gt;dist/package-*-py38-none-any.whl&lt;/code&gt; if you did not define platform details.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;finally, you can use &lt;code&gt;pip install package-*-py38-none-any.whl&lt;/code&gt; to install the package which only contains the &lt;strong&gt;pyc&lt;/strong&gt; files&lt;/li&gt;
&lt;li&gt;you can use &lt;code&gt;pip show &amp;lt;package&amp;gt;&lt;/code&gt; to check where your package get installed and also go though all folders to double confirm no source code &lt;code&gt;*.py&lt;/code&gt; files exist.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://setuptools.readthedocs.io/en/latest/easy_install.html"&gt;Easy Install in setuptools is deprecated&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wheel.readthedocs.io/en/stable/reference/wheel_convert.html"&gt;wheel convert&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/distutils/builtdist.html"&gt;Creating Built Distributions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://packaging.python.org/tutorials/installing-packages/"&gt;Installing Packages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pip.pypa.io/en/stable/reference/pip_install/"&gt;pip install&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://peak.telecommunity.com/DevCenter/EasyInstall"&gt;PEAK EasyInstall&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://peak.telecommunity.com/DevCenter/PythonEggs"&gt;PEAK PythonEggs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

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