docker learn #06: Hello Python in Alpine
Tags: docker, containers, devops
Published: 2019-11-16 05:15:25

---
title: docker learn #06: Hello Python in Alpine
published: true
description: A series of posts by Alex Ortiz of Educative, as he learns Docker
tags: docker, containers, devops
series: docker learn
cover_image: https://thepracticaldev.s3.amazonaws.com/i/ev6k6zxp9etozsabuye9.jpeg
---

So here I am with a full month of Docker under my belt, wondering what I can do to show myself my progress. To decide what to write about this week, let me start from scratch: what do I know?

I know that to run a docker container, I need a docker image. And to build a docker image, I need a Dockerfile, which contains the files plus metadata necessary to run a self-contained environment. The environment includes an operating system and the application I wish to run. For example, if I want to run a Python3 shell inside a container as if I were running it on my local machine's terminal, then I'm going to need, at a minimum, the following environment:

- an operating system on which to run Python3
- the Python3 programming language installed on the OS
- a command line interface to interact with Python3 in shell mode

In other words, I need to be able to run the Python3 shell inside a terminal inside a Linux Docker container.

Easy enough.

# Installing a Base Image...but Which One?

First up is the operating system.

Python is a pretty lightweight language that just about any operating system can handle. So I want to use a super lightweight Linux distribution to serve as my operating system for this exercise. In lieu of Ubuntu, let's go with Alpine, which is 1/10th the size.

If I run the following command from my Docker CLI, though, I'll run into trouble right away:

```
docker run alpine
```

I _won't_ want to run just this command, because if I do, then this happens:

- my Docker client calls the docker daemon via the Docker API
- it tells the daemon that I want to run an alpine container (totally is true)
- the daemon will dutifully do all this stuff:
  - pull the alpine image from Docker Hub 💪🏾
  - run the alpine image on my Docker server 💪🏾
  - run an alpine container from this image 💪🏾
  - immediately exit said container 😤

This is because the Dockerfile for an alpine image has but one command that runs as default: `"/bin/sh"`.

So when I tell Docker to pull or run alpine, it does that, and the base image runs, and it does what it's supposed to, but then the shell a) doesn't receive any additional instructions, b) determines that there is nothing for it to do, and consequently c) stops running, which leaves the container without a process to run, causing the container to be terminated (exited). No process, no container. I get it.

> **Side Note 1**: This can be confirmed with the `docker ps -a` command, which will show that an alpine container did indeed momentarily run but was then exited. 

This is of course no good to me if what I want to do is run Python3 inside a container.

So it's time to break out the useful **-ti** flag.

## Using `-ti` To Run an Interactive Terminal

For all the above reasons, I run the following instead:


```
docker run -ti alpine
```

There we go. Now the docker daemon will do its thing again, but _this_ time, the alpine container won't exit. The combo of the two Docker flags `t` and `i` will instruct Docker to please allocate me a terminal and patiently listen for my input.

I'll now be able to use the built-in shell to move on to my next step: installing Python3 inside this container.

# Adding Python3 with the Alpine Package Manager, apk

Alpine Linux doesn't come with Python3 pre-installed. You have to install it manually. It's very simple to do with the alpine package manager, `apk`. A quick check of the [Alpine Linux APK website](https://pkgs.alpinelinux.org/packages?name=python3&branch=edge) shows that **python3** is indeed one of the packages.

Since I'm now running an Alpine Linux docker container with an interactive terminal waiting for me to provide further instruction, I can proceed:

```
apk add python3
```

This will install python3 on my alpine operating system inside the Docker container. I can confirm the installation afterwards by typing `python3 --version` into the alpine terminal, which outputs `Python 3.7.5`:

```
/ # python3 --version
Python 3.7.5
```

We're in business! On to the final step: launching Python3 in shell mode.


> **Side Note 2**: By the way, the presence of `/ #` indicates that I'm in the interactive shell terminal within my alpine container.


# Actually Running Python3 in Shell Mode

At last, I can run Python3. Since I just installed python3, I can simply run it by typing `python3`:

```
/ # python3
Python 3.7.5 (default, Oct 17 2019, 12:25:15) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
```

The presence of `>>>` indicates that I'm in Python3's shell mode. That is, I am now actually running the Python3 application. Now for the fun stuff! 😎

# Taking on a Small Python Challenge

Now that I have Python running in shell mode inside an interactive shell terminal inside an Alpine Docker container, I can take on a fun challenge. For example, my Educative team [recently wrote a blog post](https://www.educative.io/blog/level-up-python-skills) with six fun Python challenges.

Let's try two of them right now :).

## Challenge #1: World, Can You Hear Me?

Here was my team's prompt to readers:

![Challenge #1 from Level up your Python skills with these 6 challenges](https://thepracticaldev.s3.amazonaws.com/i/bgfwmjnq5eu1x9bnjjfa.png)

Challenge accepted. In my Docker container, I type this:

```
>>> print("Hello World\nLet's Learn Python\nSincerely, Alex")
```

And the Python shell prints the following:

```
Hello World
Let's Learn Python
Sincerely, Alex
```

## Challenge #2: Some Maths and Physics

Here was my team's prompt to readers:


![Challenge #2 from Level up your Python skills with these 6 challenges](https://thepracticaldev.s3.amazonaws.com/i/5k5o4m5r1uzuef68xen9.png)

They also provided the following values:

G = 6.67 x 10^<sup>-11</sup>
M<sub>Sun</sub> = 2.0 x 10<sup>30</sup>
m<sub>Earth</sub> = 6.0 x 10<sup>24</sup>
r = 1.5 x 10<sup>11</sup>

So in my Docker container, I created variables `G`, `M`, `m`, and `r` and stored their respective values in each, using Python-friendly scientific notation. Then I created the variable `grav_force` as instructed, though converting it into the Python-friendly notation. Finally, I instructed Python to print the variable I just created, outputting the result of Newton's beautiful gravitational force equation.

Putting this all together, it was like so:

```
>>> G = 6.67e-11
>>> M = 2.0e30
>>> m = 6.0e24
>>> r = 1.5e11
>>> grav_force = (G*M*m)/(r*r)
>>> print(grav_force)
3.5573333333333336e+22
```

Close enough, and not bad for this all running inside a Docker container! :)

I then type `(exit)` to exit the Python3 shell, and then `exit` to exit the alpine container I've been using. To confirm that the daemon terminated the container, I use `docker ps -a -l`, and it shows me that the last container that ran indeed was exited, seconds ago.

# Wrapping Up

I've once again run out of time to write all the other cool stuff I learned this week or am excited about with respect to Docker. But I'm really happy that I got to "test" myself by starting from what I've learned so far and then moving towards a tangible demonstration of my learnings—even crossing over into Python-land.

And did I mention how sweet it is that we just saw how easy and cool it is to run Python-in-Linux-in-Docker?

Very cool indeed. Till next time!

{% twitter 1195572759645917184 %} 

---

You know the drill: hit the DEV.to Follow button, follow me on Twitter [@alexoeducative](https://twitter.com/alexoeducative), and definitely visit [our blog](Educative.io/blog). Chat or comment below if you'd like to add any Alpine or Docker knowledge!