<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Michal Slovík</title>
    <description>The latest articles on DEV Community by Michal Slovík (@michalslovik).</description>
    <link>https://dev.to/michalslovik</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%2F1139676%2F1a896df5-d08b-4103-a013-56b496afb0bd.jpeg</url>
      <title>DEV Community: Michal Slovík</title>
      <link>https://dev.to/michalslovik</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/michalslovik"/>
    <language>en</language>
    <item>
      <title>Python Interpreter in Docker and Pyspark Tests in Docker</title>
      <dc:creator>Michal Slovík</dc:creator>
      <pubDate>Tue, 26 Sep 2023 11:22:25 +0000</pubDate>
      <link>https://dev.to/michalslovik/python-interpreter-in-docker-and-pyspark-tests-in-docker-4o23</link>
      <guid>https://dev.to/michalslovik/python-interpreter-in-docker-and-pyspark-tests-in-docker-4o23</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;There are two main ideas behind this article: &lt;code&gt;security&lt;/code&gt; and &lt;code&gt;mobility&lt;/code&gt;. When you create your environment only on your server, laptop, Raspberry Pi, etc., it may be great, but without any backup, regular updates, or automation, it can easily become a &lt;a href="https://martinfowler.com/bliki/SnowflakeServer.html" rel="noopener noreferrer"&gt;SnowflakeServer&lt;/a&gt; anti-pattern. Python offers virtual environments to avoid this issue.&lt;/p&gt;

&lt;p&gt;Another point is the security of the environment. Virtual environments are great, but they can easily become insecure. You should use the latest major version of Python and be careful when installing and using external libraries. It is possible for a malicious module with the same name to be in a popular open-source library and find its way into the system path. If the malicious module is found before the actual module, it will be imported and could be used to exploit applications that have it in their dependency tree. To prevent this, you must ensure that you use either an absolute import or an explicit relative import, as the latter guarantees the import of the actual and intended modules.&lt;/p&gt;

&lt;p&gt;Fortunately, Docker can keep many of these things in mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Docker as a Python Interpreter
&lt;/h2&gt;

&lt;p&gt;There are a few different approaches to using Docker as a Python interpreter, depending on your needs. If you have an existing Python application that you want to run in a Docker container, you can “dockerize” your application by creating a Docker image.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dockerize your Python application
&lt;/h3&gt;

&lt;p&gt;Docker images are a great way to ensure that your application runs consistently across different machines and servers. By containerizing your application, you can separate it from the underlying hardware and operating system as much as possible, making it easier to move and deploy.&lt;/p&gt;

&lt;p&gt;To dockerize your Python application, you'll need to create a Dockerfile that specifies the base image, any dependencies you need to install, and the command to run your application. For more info see &lt;a href="https://www.docker.com/blog/how-to-dockerize-your-python-applications/" rel="noopener noreferrer"&gt;Dockerize your python application&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of using Docker as a Python interpreter
&lt;/h3&gt;

&lt;p&gt;Using Docker as a Python interpreter has a number of benefits. For one, it makes it easier to ensure that your application runs consistently across different environments. Additionally, it can simplify the process of managing dependencies, as all the dependencies for your application can be included in the Docker image. Finally, by using Docker, you can avoid some of the pitfalls of maintaining a "snowflake server" - a server that is difficult to reproduce and maintain over time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Docker as a remote Python interpreter
&lt;/h3&gt;

&lt;p&gt;What about when you want to develop and build your application from scratch and you want to use separated python interpreter.&lt;br&gt;
There is an existing solution like &lt;a href="https://www.jetbrains.com/help/pycharm/using-docker-as-a-remote-interpreter.html#example" rel="noopener noreferrer"&gt;PyCharm from JetBrains&lt;/a&gt;, but it requires Professional version of PyCharm.&lt;/p&gt;

&lt;p&gt;Visual Studio Code can handle &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers" rel="noopener noreferrer"&gt;Dev Containers plugin&lt;/a&gt; this job. Basically, you can attach to a Docker container that contains Python.&lt;/p&gt;

&lt;p&gt;First step is to create some simple &lt;code&gt;Dockerfile&lt;/code&gt;&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="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:latest&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; . ./&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Build &lt;code&gt;docker build -t pyground .&lt;/code&gt; and start docker container &lt;code&gt;docker run -it --rm --name pyground pyground:latest&lt;/code&gt;. After these command your python interpreter is alive, you need to attach with your code editor (vscode in our example), however when you have terminal you can basically connect and run whatever you want.&lt;/p&gt;

&lt;p&gt;In VSCode via plugin pick up new interpreters&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%2Fu0293nsazx5z6syhm1b1.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%2Fu0293nsazx5z6syhm1b1.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Attach your running docker containers&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%2F98rvd2swpweqb2jn62v3.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%2F98rvd2swpweqb2jn62v3.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that you should see new visual studio window open and in left corner attached running containers&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%2Fp113eq8gh0a3k3oik1vw.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%2Fp113eq8gh0a3k3oik1vw.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Via terminal I get current python version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@704b87b076d8:~# python &lt;span class="nt"&gt;--version&lt;/span&gt;
Python 3.11.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have files in the same folder as your Dockerfile, you can run and use them in the container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@704b87b076d8:~# &lt;span class="nb"&gt;ls&lt;/span&gt; /app/
Dockerfile  solver.py
root@704b87b076d8:~# python /app/solver.py 
a: 1
b: 10
c: 1
&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;-0&lt;/span&gt;.10102051443364424, &lt;span class="nt"&gt;-9&lt;/span&gt;.898979485566356&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Code for this &lt;code&gt;solver.py&lt;/code&gt; is available here &lt;a href="https://www.jetbrains.com/help/pycharm/using-docker-as-a-remote-interpreter.html#example" rel="noopener noreferrer"&gt;JetBrains Example&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After you done with your work you can stop docker container and vscode should automatically detach that container. Keep in mind option &lt;code&gt;--rm&lt;/code&gt; will remove docker container after run. For more a persistent solution, take a look at &lt;a href="https://docs.docker.com/storage/bind-mounts/" rel="noopener noreferrer"&gt;bind mount solution by Docker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can improve Dockerfile to be ready with preinstalled libraries. Best practices for python libraries is to use &lt;code&gt;requirement.txt&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;numpy==1.24.2
pandas==1.5.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And improved Dockerfile:&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="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:latest&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; pip

&lt;span class="k"&gt;ADD&lt;/span&gt;&lt;span class="s"&gt; requirements.txt .&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Build docker image with specific &lt;code&gt;Dockerfile&lt;/code&gt; filename &lt;code&gt;docker build -t pyground2 -f .\Dockerfile-with-requirements.dockerfile .&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And then we can test it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;Python&lt;/span&gt; &lt;span class="mf"&gt;3.11&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Mar&lt;/span&gt;  &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;46&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;GCC&lt;/span&gt; &lt;span class="mf"&gt;10.2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;20210110&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;linux&lt;/span&gt;
&lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;help&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;copyright&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;credits&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;license&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;information&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can put some pre-configuration in Dockerfile or sample files. This way we can prepare the same environment for colleagues or students. Everyone will have the same version of python along with same versions of all libraries and dependencies.&lt;/p&gt;

&lt;p&gt;One last note: Don’t overfill your Dockerfile, always check if you need these things in your images, for example my base &lt;code&gt;pyground&lt;/code&gt; image with the latest version of python &lt;code&gt;Python 3.11.2&lt;/code&gt; was 925 MB and with the pandas and numpy libraries we got over 1 GB!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; docker images
REPOSITORY        TAG       IMAGE ID       CREATED          SIZE
pyground          latest    c69a7214f5e5   33 minutes ago   925MB
pyground2         latest    bfe8fc2400e4   7 minutes ago    1.12GB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Docker containers as test instances for PySpark
&lt;/h2&gt;

&lt;p&gt;We used the previous example for testing purposes. We have several goals that we need to achieve. First, we need to ensure that we are able to test our code locally (on any operating system and any hardware). We also need to check our code during the deployment pipeline. Docker is perfect for all these tasks. Moreover, our code is written for PySpark.&lt;/p&gt;

&lt;p&gt;First, we need to configure a Dockerfile containing PySpark and Java.&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="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; IMAGE_VARIANT=slim-buster&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; OPENJDK_VERSION=8&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; PYTHON_VERSION=3.9.8&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;python:${PYTHON_VERSION}-${IMAGE_VARIANT}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;py3&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; openjdk:${OPENJDK_VERSION}-${IMAGE_VARIANT}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, more lines need to be explained. We use the basic &lt;code&gt;slim-buster&lt;/code&gt; image. This &lt;code&gt;slim&lt;/code&gt; image generally contains only the minimal packages needed to run Python. The &lt;code&gt;buster&lt;/code&gt; is the codename for the stable version of Debian, whose release is 10.4. This python image was based on it.&lt;/p&gt;

&lt;p&gt;Next, we will use a second base image &lt;code&gt;openjdk&lt;/code&gt; with a similar codename and a Java version of OPENJDK_VERSION=8.&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="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; PYSPARK_VERSION=3.2.0&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nt"&gt;--no-cache-dir&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;&lt;span class="nv"&gt;pyspark&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PYSPARK_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;With run command we install &lt;code&gt;PySpark&lt;/code&gt; (version 3.2.0) itself and then we install all system dependencies and often used libraries.&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="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; app&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; build-essential libxml2
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . /app&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip3 &lt;span class="nb"&gt;install &lt;/span&gt;cython numpy pytest pandas coverage pyspark_test dummy_spark IPython pytest-cov
&lt;span class="k"&gt;RUN &lt;/span&gt;pip3 &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; python3 -m coverage run --source=. -m pytest -v test/ &amp;amp;&amp;amp; coverage report &amp;amp;&amp;amp; coverage xml &amp;amp;&amp;amp; cat coverage.xml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last command is for the test itself. Here we call &lt;code&gt;coverage&lt;/code&gt; and &lt;code&gt;pytest&lt;/code&gt; tools. This command will run all the unit tests in the &lt;code&gt;test/&lt;/code&gt; folder. A test report is generated and a coverage message is returned (shown).&lt;/p&gt;

&lt;h2&gt;
  
  
  Lift and shift
&lt;/h2&gt;

&lt;p&gt;As mentioned earlier, we can reuse a Dockerfile in multiple environments. Here are some examples where we can use our previous Dockerfile image (&lt;code&gt;sparktest&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;In an Azure Devops pipeline, we can use following approach to run this image and get a coverage report:&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="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Docker@2&lt;/span&gt;
    &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Build&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;an&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;image'&lt;/span&gt;
    &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;repository&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sparktest'&lt;/span&gt;
      &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;build'&lt;/span&gt;
      &lt;span class="na"&gt;Dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;**/Dockerfile'&lt;/span&gt;
      &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;latest'&lt;/span&gt;

  &lt;span class="pi"&gt;-&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;docker run -e PYTHONPATH=./src -v :/app --name sparktest sparktest &lt;/span&gt;
      &lt;span class="s"&gt;CONTAINER_ID=`docker ps -aqf "name=sparktest"`&lt;/span&gt;
      &lt;span class="s"&gt;docker cp $CONTAINER_ID:/app/coverage.xml test-coverage.xml&lt;/span&gt;
    &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Image&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;unittest&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;by&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Docker"&lt;/span&gt;
    &lt;span class="na"&gt;workingDirectory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ parameters.appPath }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;docker-compose.yaml&lt;/code&gt; we can specify the Dockerfile with context:&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;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.9"&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;test&lt;/span&gt;&lt;span class="pi"&gt;:&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;PYTHONPATH=./src&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sparktest"&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./Dockerfile&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;./our_current_project:/app&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python3 -m coverage run --source=. -m pytest -v test/ &amp;amp;&amp;amp; coverage report &amp;amp;&amp;amp; coverage xml &amp;amp;&amp;amp; cat coverage.xml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And of course you can build and run that image from your local machine.&lt;/p&gt;

&lt;p&gt;In summary, using Docker as a Python interpreter can be a powerful tool for managing your Python applications and development environment. By containerizing your application or development environment, you can ensure that it runs consistently across different machines and servers, simplify dependency management, and avoid the pitfalls of maintaining a snowflake server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/docs/devcontainers/attach-container" rel="noopener noreferrer"&gt;https://code.visualstudio.com/docs/devcontainers/attach-container&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/develop/develop-images/dockerfile_best-practices/" rel="noopener noreferrer"&gt;https://docs.docker.com/develop/develop-images/dockerfile_best-practices/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/visualstudio/docker/tutorials/docker-tutorial" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/visualstudio/docker/tutorials/docker-tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/69326427/select-interpreter-of-docker-container-in-the-vscode" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/69326427/select-interpreter-of-docker-container-in-the-vscode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://martinfowler.com/bliki/SnowflakeServer.html" rel="noopener noreferrer"&gt;https://martinfowler.com/bliki/SnowflakeServer.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/alvarocavalcanti/setting-up-a-python-remote-interpreter-using-docker-1i24"&gt;https://dev.to/alvarocavalcanti/setting-up-a-python-remote-interpreter-using-docker-1i24&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/54954187/docker-images-types-slim-vs-slim-stretch-vs-stretch-vs-alpine" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/54954187/docker-images-types-slim-vs-slim-stretch-vs-stretch-vs-alpine&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Originally published at &lt;a href="https://mishco.gitlab.io/post/2023-03-08-docker-with-multifunctionality/" rel="noopener noreferrer"&gt;https://mishco.gitlab.io&lt;/a&gt; on March 8, 2023.&lt;/p&gt;

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