How to setup python environment in docker in my case? - python

I am trying to setup my python environment in docker.
My docker image is like this:
FROM python:2.7
# updating repository
RUN apt-get update
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
COPY requirements.txt requirements.txt
RUN pip install --no-cache -r requirements.txt
EXPOSE 8888
COPY . .
CMD ["python", "test.py"]
with this build command:
docker build -t ml-python-2.7 .
After image is built,
I ran
docker run -it --rm --name ml-container ml-python-2.7 python test.py
My sample test.py
print('test here')
It works when I first run this command.
docker run -it --rm --name ml-container ml-python-2.7 python test.py
but after I change the test.py to print('second test')
and run the above command again, it still output test here.
How do I make sure it updates automatically or if there is more elegant way to do this?
Thanks!

Docker does not store the changes you are making to files inside the container unless you commit it. If you want it to do so, you need to do a Docker Commit like:
docker commit <CONTAINER NAME HERE>
Or you could mount a local folder to the docker image like this:
docker run -ti -v ~/folder_in_host:/var/log/folder_in_container <IMAGE NAME HERE>

Related

Python docker image fails because of missing shell / bash in the image

I have the following Dockerfile:
FROM python:3-alpine
WORKDIR /usr/src/app
COPY requirements.txt .
RUN pip install -qr requirements.txt
COPY target-watch.py .
CMD ["python3", "./target-watch.py"]
If I deploy this to a Kubernetes cluster the build went fine, but I got an error from the Kubernetes logs. To verfiy my image I run the following command:
docker run --rm -it --entrypoint /bin/bash docker-conveyor.xxx.com/myorg/my_cron_jobs:2021.12.08_03.51_abcdef
Which gives me this response:
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "/bin/bash": stat /bin/bash: no such file or directory: unknown.
How can this be fixed? I assume a shell is missing in my image. How do i have to change my Dockerfile to make it work without any errors?
Your container image doesn't have bash so you should use /bin/sh instead of /bin/bash.
docker run --rm -it --entrypoint /bin/sh docker-conveyor.xxx.com/myorg/my_cron_jobs:2021.12.08_03.51_abcdef
Alpine docker image doesn't have bash installed by default. You will need to add the following commands to get bash:
RUN apk update && apk add bash
If you're using Alpine 3.3+ then you can just do
RUN apk add --no-cache bash

I cannot containerise my python code in a docker container

I am learning docker. I want to practice how to see logs inside of a docker container once I run a python image.
This is the python code I want to execute:
#loop.py
#loop.py
import time
while True:
print('test')
time.sleep(3)
This is the docker file:
FROM python:3.8-slim-buster
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
COPY requirements.txt .
RUN python -m pip install -r requirements.txt
WORKDIR /app
COPY . /app
RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app
USER appuser
CMD ["python", "loop.py"]
I build the image like this:
docker build -t image_test .
Once it is created ( I can see it doing docker image ls) I want to run it, I have different ways but the container is created and is terminated instantly:
docker run <imageID>.
I have tried too:
docker docker run <imageID> sleep infinity. Then I can do: docker exec -it <containerID> bash and I can run inside the container python loop.py but it automatically ends.
I modified the CMD like this as well:
CMD ["python","-u", "loop.py"]
I have tried:
docker run -it --entrypoint=/bin/bash image_test and I directly go to the terminal inside of the container, but if I execute the python code as before, it automatically ends, instead of run the infinite loop.
why?
You don't need bash to run a python program. You can use it to exec into a running container. But the container will be running as long as the python is connected to the stdout.
I ran these commands and they all work on my machine.
sudo docker run image_test
sudo docker run -d image_test
sudo docker ps
sudo docker logs -f 041
sudo docker exec -ti 041 bash
sudo docker stop 041
sudo docker rm 041

bulding docker image for several script

I have 2 python script and one R script but the main scripts to run are the python script (I call the R script in one of the python scripts). I have to dockerize all these script. to do so I have made Dockerfile which is here:
FROM python:3.7
WORKDIR /opt/app/
ADD ./ ./
RUN pip3.7 install -r ./requirements.txt
CMD python3.7 qc.py
CMD python3.7 cano.py
So, I have 2 questions:
1- shall I include the R script in the Dockerfile? (that is myscript.r)
2- before running the docker image I need to build the image. if I had one script (qc.py) to run I will use the following command to build image:
sudo docker build -t qc .
but what would be the command to build the image for the Dockerfile with more than one script?
The docker image produced when calling docker build should stay separate from the execution of the scripts.
To execute something that's inside of an image, you can use docker run.
Using your example:
This is the directory with your Dockerfile in it:
$ tree .
├── Dockerfile
├── cano.py
├── myscript.r
├── qc.py
└── requirements.txt
0 directories, 5 files
We want to build a docker image that has all of the R and Python scripts in it, and all of the dependencies to execute those scripts, but we don't necessarily want to run them yet.
In your Dockerfile, you don't have the dependencies needed to run myscript.r because the base image (FROM python:3.7) doesn't have the required packages installed. I looked up what was required to run an R script in the r-base repo on docker hub and in the repo on github, and then added it to the Dockerfile.
FROM python:3.7
# Install the dependencies for R
RUN apt-get update && apt-get install -y r-base r-base-dev r-recommended
# Add all of the scripts to the /opt/app/ path inside of the image
ADD . /opt/app/
# Change the working directory inside of the image to /opt/app/
WORKDIR /opt/app/
# Install the python dependencies in /opt/app/requirements.txt using pip
RUN pip3.7 install -r ./requirements.txt
# This command just shows info about the contents of the image. It doesn't run any
# scripts, since that will be done _AFTER_ the image is built.
CMD pwd && ls -AlhF ./
Notice that the default CMD doesn't run any of the scripts. Instead we can do that using the docker run command from the terminal:
# The --rm removes the container after executing, and the -it makes the container interactive
$ docker run --rm -it qc python cano.py
Hello world! (from cano.py)
Now, putting it all together:
# Starting in the directory with your Dockerfile in it
$ ls .
Dockerfile cano.py myscript.r qc.py requirements.txt
# Build the docker image, and tag it as "qc"
$ docker build -t qc .
Sending build context to Docker daemon 6.656kB
Step 1/6 : FROM python:3.7
---> fbf9f709ca9f
Step 2/6 : RUN apt-get update && apt-get install -y r-base r-base-dev r-recommended
# ...lots of output...
Successfully tagged qc:latest
# Run the scripts
$ docker run --rm -it qc python cano.py
Hello world! (from cano.py)
$ docker run --rm -it qc python qc.py
Hello world! (from qc.py)
$ docker run --rm -it qc Rscript myscript.r
[1] "Hello world! (from myscript.r)"
I've collected all of the example code in this github gist to make it easier to see everything in one place.

How to start the container in Docker in my case

I am trying to setup my python environment in docker.
My docker image is like this:
FROM python:2.7
# updating repository
RUN apt-get update
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
COPY requirements.txt requirements.txt
RUN pip install --no-cache -r requirements.txt
EXPOSE 8888
COPY . .
CMD ["python", "test.py"]
with this build command:
docker build -t ml-python-2.7 .
After image is built,
I ran
docker run -it --name ml-container -v ${PWD}:/usr/src/app ml-python-2.7 python test.py
My sample test.py
print('test here')
It works when I first run this command and update the output every time I changed my test.py
The problem is if I want to keep the container and remove the --rm option, the container quit and I can't run
docker run -it --name ml-container -v ${PWD}:/usr/src/app ml-python-2.7 python test.py
anymore because it says there is a container name conflict. How do I keep the container and run the test.py again after that file is updated? Thanks!
After the container has exited, you can start it again using docker start. More information here: How to continue a docker which is exited

Docker Container stops immediately (Flask/Python/Megatutorial)

I've been following the flask megatutorial by the inestimable Miguel Grinberg (https://learn.miguelgrinberg.com/read/mega-tutorial/ch19.html), and recently hit on a snag in deployment.
The docker run command starts the container and then it immediately stops. It isn't showing up in docker ps -a either. I've trawled through lots of responses here which seem to suggest that the solution is to add "-it" to the docker run command however this does not solve the issue.
Here's my dockerfile:
FROM python:3.6-alpine
RUN adduser -D james
WORKDIR /home/myflix
COPY requirements.txt requirements.txt
RUN python -m venv venv
RUN venv/bin/pip install -r requirements.txt
RUN venv/bin/pip install gunicorn pymysql
COPY app app
COPY migrations migrations
COPY myflix.py config.py boot.sh ./
RUN chmod +x boot.sh
ENV FLASK_APP myflix.py
RUN chown -R james:james ./
USER james
EXPOSE 5000
ENTRYPOINT ["./boot.sh"]
My image is called myflix:secondattempt.
The command used to start the container:
sudo docker run --name myflixcont -d -p 8000:5000 --rm myflix:secondattempt
As I said, I've already tried dropping in various combinations of "-i" and "-t" in front of the "-d" to no avail.
-it means interactive tty.
You can not use -it in conjunction with -d which means detached.
Remove -d and add -it:
docker run --name myflixcont -it -p 8000:5000 --rm myflix:secondattempt
Another point (with the purpose of helping you) is that ENTRYPOINT runs in exec mode. meaning that it does not start a bash or dash itself. You should specify it manually and explicitly:
ENTRYPOINT ["sh", "file.sh"]
# or
ENTRYPOINT ["bash", "file.sh"]

Categories

Resources