We will create a simple web server with Python and create a docker image with the same. Our target it to run the docker image and be able to access this web server from our browser.
Creating a simple webserver with Python
First, we need to create a simple index.html file that will be displayed to any user accessing the website.
<html>
<head>
<title>Python Web Server!</title>
</head>
<body>
<h1>This is really working!</h1>
<p>Web server is indeed serving you. Be happy!</p>
</body>
</html>
Next, we will see the actual python code that shall create the webserver:
import http.server import socketserver
PORT = 8080 Handler = http.server.SimpleHTTPRequestHandler
with socketserver.TCPServer((“”, PORT), Handler) as httpd: print(“Server launched at “, PORT) httpd.serve_forever() Thanks to https://www.afternerd.com/blog/python-http-server/ for the tutorial on this.
We shall save this into a file called python-webserver.py. Both this python file and the index.html shall be in a directory called python-webserver.
To test if the webserver runs, go into the command prompt, navigate to this folder and type in:
C:\Users\Pradeep\python-webserver>python python-webserver.py
Server launched at 8080
Next, open a browser and navigate to “http://localhost:8080/“.This should display the index.html page.
Creating the required Dockerfile
We now will create the Dockerfile required to create the image.
Create a Dockerfile inside the same folder as the index.html and the python-webserver.py file.
We need the following to be part of the image
Base alpine image,
python and pip installations,
http.server python module installed
The index.html and python-webserver.py
Launching the python webserver on the container initialization
# Import a base image
FROM alpine
# Install Python and the required dependencies
RUN apk add –no-cache python3 && pip3 install –upgrade pip setuptools
# Create a work directory to copy the files into (to prevent accidental overrides in the root directory)
WORKDIR /usr/simplepythonwebserver
# Copy the required files from the local folder to the image file space
COPY ./ ./
# Open the shell
RUN sh
# Install the required python modules
RUN pip install httpserver
# socketserver is a library and hence no need to install it
# Launch the webserver
CMD [“python3”, “python-webserver.py”]
The COPY ./ ./ copies all the files present in the current directory (which we specify in the build command by using the docker build .) to the path specified inside the container file space (using the WORKDIR instruction).
Now, let’s build this image:
C:\Users\Pradeep\python-webserver> docker build -t pradeep87blore/simplepythonwebserver .
Sending build context to Docker daemon 4.096kB
Step 1/6 : FROM alpine
—> 5cb3aa00f899
Step 2/6 : RUN apk add –no-cache python3 && pip3 install –upgrade pip setuptools
—> Using cache
—> 1a61d56d8529
Step 3/6 : COPY ./ ./
—> 5479e2d3ad13
Step 4/6 : RUN sh
—> Running in bed31018bf98
Removing intermediate container bed31018bf98
—> 195865d61945
Step 5/6 : RUN pip install httpserver
—> Running in 8a4246c979d3
Collecting httpserver
Downloading https://files.pythonhosted.org/packages/27/1e/d8d4bed911b0ef911863c8b06dc2b3f1748980703eaacce846ccda73301b/httpserver-1.1.0-py2.py3-none-any.whl
Collecting docopt (from httpserver)
Downloading https://files.pythonhosted.org/packages/a2/55/8f8cab2afd404cf578136ef2cc5dfb50baa1761b68c9da1fb1e4eed343c9/docopt-0.6.2.tar.gz
Installing collected packages: docopt, httpserver
Running setup.py install for docopt: started
Running setup.py install for docopt: finished with status ‘done’
Successfully installed docopt-0.6.2 httpserver-1.1.0
Removing intermediate container 8a4246c979d3
—> a2ba484113f7
Step 6/6 : CMD [“python3”, “python-webserver.py”]
—> Running in f975cb41c93b
Removing intermediate container f975cb41c93b
—> 3e982451d5ef
Successfully built 3e982451d5ef
Successfully tagged pradeep87blore/simplepythonwebserver:latest
Note, the above logs are not from the first time clean run and hence there were some cached images already.
Before launching the container, one thing to keep in mind is that the container has it’s own port space. This means that, even if we get the webserver up and running inside the container, the port 8080 on the container doesn’t map to the port 8080 on the host machine. We need to manually make this mapping. Note that this is only for requests going into the docker container. Requests originating from within the container can reach the external ports as we see the python installations, pip module downloads, etc. doing so already.
To specify this port mapping, we need to add the -p param in the docker run command:
docker run -p 8080:8080 -it pradeep87blore/simplepythonwebserver
If you are getting the following error:
C:\Program Files\Docker\Docker\Resources\bin\docker.exe: Error response from daemon: driver failed programming external connectivity on endpoint awesome_burnell (5dadcd82e269eaf058e41ef5934a1a3571e0c4f2e63fd915115345c5cacea251): Error starting userland proxy: mkdir /port/tcp:0.0.0.0:5000:tcp:162.27.0.5:8080: input/output error.
Try restarting the docker from the docker settings. This fixed the issue for me
PS C:\Users\Pradeep\python-webserver> docker run -p 5000:8080 -it pradeep87blore/simplepythonwebserver
Server launched at 8080
If I try to browse http://localhost:5000/, it shows the index.html page we created earlier.
If you want to check where the files are now situated, run the following:
C:\Users\Pradeep\python-webserver>docker run -it -p 5000:8080 pradeep87blore/simplepythonwebserver sh
/usr/simplepythonwebserver # ls
Dockerfile index.html python-webserver.py
We can see that the files were created under the /usr/simplepythonwebserver path.
Pushing the image to the docker hub
Once you are satisfied with the image created, you can push the same to the docker hub:
C:\Users\Pradeep\python-webserver> docker push pradeep87blore/simplepythonwebserver
The push refers to repository [docker.io/pradeep87blore/simplepythonwebserver]
24d15f0d543a: Pushed
0b9c20b4e03f: Pushed
5e854bef0cb0: Pushed
bcf2f368fe23: Mounted from library/alpine
latest: digest: sha256:49f6b6e3cc22a2b1e93ab85d0536cccb64b237a2bce678d4e7a89cc4af5c978a size: 1156
PS C:\Users\Pradeep\python-webserver>
Check your repositories in the docker hub to see if this image was pushed correctly or not. This repo is available at: https://cloud.docker.com/u/pradeep87blore/repository/docker/pradeep87blore/simplepythonwebserver
To test if this is working fine, I deleted all the images from my system using the
docker system prune -a
Do note that this will delete all your containers and images. Proceed only if you are OK with that!
C:\Users\Pradeep\python-alpine>docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
Thus, all images removed from the system. If this is still showing your image for you, you might need to run the docker ps -a to check if there are any active containers. You can kill those and prune the system again.
Next, I ran the docker run with the following and could see the image getting downloaded and lauching:
C:\Users\Pradeep\python-alpine>docker run -it -p 5000:8080 pradeep87blore/simplepythonwebserver
Unable to find image ‘pradeep87blore/simplepythonwebserver:latest’ locally
latest: Pulling from pradeep87blore/simplepythonwebserver
8e402f1a9c57: Pull complete
2524982b0b77: Pull complete
e2b1f933ffdf: Pull complete
dfdcda915d9a: Pull complete
Digest: sha256:49f6b6e3cc22a2b1e93ab85d0536cccb64b237a2bce678d4e7a89cc4af5c978a
Status: Downloaded newer image for pradeep87blore/simplepythonwebserver:latest
Server launched at 8080
142.41.0.5 – – [23/Mar/2019 21:35:40] “GET / HTTP/1.1” 200 –
Launch the localhost:5000 in the browser and it should show the proper content now.
Thus, our simple web server, created with python on an alpine base image, is working fine!
Comments