Docker ASPNET Core container with Python installed - python-2.7

I have an application that is running some processes and exposes them through WebAPI. Part of these processes need to execute Python scripts through the IronPython library. For this to happen though, Python 2.7 must also be installed on the system.
Has anyone solved this problem by figuring out how to install Python in the ASPNET Core Docker image (or by any other means). The only other hack I can think of it putting the Python executable into a dependency directory for the API.
Our current Docker File contents:
FROM microsoft/aspnetcore:2.0
ARG source
WORKDIR /app
EXPOSE 80
COPY ${source:-obj/Docker/publish} .
ENTRYPOINT ["dotnet", "Api.dll"]

You can use the RUN command to install it on the image. Simply add the following to your Dockerfile.
The image I pulled from Dockerhub seemed to be running Debian Linux as the base OS so the following should work. If it's another linux distro as the base in your instance, try yum instead or for windows OS chocolatey.
FROM microsoft/aspnetcore:2.0
RUN apt-get update -y && apt-get install python2.7 -y
ARG source
WORKDIR /app
EXPOSE 80
COPY ${source:-obj/Docker/publish} .
ENTRYPOINT ["dotnet", "AIA.Vietnam.dll"]
Now the python executable should be available in /usr/bin/python2.7

Related

Install apt packages in docker via build step and copy

When you have a complicated RUN apt-get install section that you reuse over multiple docker images, what is the best way to reuse it?
The options that I think we have are
copy-paste the RUN command n times across your Dockerfiles (this is what I do today)
make a docker image and use it as a build step + COPY --from=builder... (this is what I wan't, but I don't konw how to do it).
I am thinking of something like this:
Dockerfile with reusable apt install command, tagged as my-builder-img:
FROM debian:buster
RUN ... apt-get install ...
Dockerfile that reuses that complicated install:
FROM my-builder-img as builder
#nothing here
FROM debian:buster
COPY --from=builder /usr/bin:/usr/bin # (...???)
TL;DR how to reuse apt-get install from a previus image onto a new image.
You just use the image you put all the packages in directly.
Multi-stage builds shine when you are creating an artifact and copying that to a new image. If you are just installing packages those will exist in the image.
Dockerfile with packages you want:
FROM debian:buster
RUN ... apt-get install ...
Tag it as my-image.
Now, just use that image in other Dockerfiles and the packages installed will be available.
FROM my-image:latest
# other directives...

ModuleNotFoundError: No module named 'flask_sqlalchemy' error observer while i do running the docker images

I am getting ModuleNotFoundError No module named 'flask_sqlalchemy' when try to docker run of builded docker images.The same python flask run using terminal is working fine for me but not in docker?
FROM python:3.6
ADD . /app
WORKDIR /app
RUN pip install flask gunicorn
EXPOSE 8000
CMD ["gunicorn", "-b", "0.0.0.0:8000", "app"]
The good practice is to save file with installed pip packages, e.g. in requirements.txt. (preferably with only needed packages, e.g. when you are using pyevn).
This is done by pip freeze > requirements.txt (when located on local machine, in terminal).
Then, all you should do is replace RUN pip install flask gunicorn with RUN pip install -r requirements.txt and all installed packages on the local machine will be installed in the docker too.

App Engine: ImportError: No module named _gdal

How to enable python 2.7 library like GDAL in Google App Engine standard? Currently there are linux python-modules in lib-folder in app engine, but when trying to run the code through endpoints, app engine gives internal server error: ImportError: No module named _gdal. I'm using pygdal version 2.2.3.3. Should the libgdal (demanded for pygdal)be installed also on app engine, and if so, how to do it? I installed GDAL locally into lib folder (using ubuntu bash on windows10) following these instructions using this syntax: sudo pip install --target lib --requirement requirements.txt --ignore-installed as it says here. Please help!
From What compiler can I use to build GDAL/OGR?
GDAL/OGR is written in ANSI C and C++. It can be compiled with all modern C/C++ compilers.
Which means it's incompatible with the (1st generation/python 2.7) standard environment Pure Python sandbox requirement:
All code for the Python runtime environment must be pure Python, and
not include any C extensions or other code that must be compiled.
You may want to look at the flexible environment instead. Probably with a custom runtime, see Up-to-date pip with AppEngine Python flex env?
Google App Engine's standard environment for Python27 only supports a specific set of third-party libraries that use C-extensions, listed here. pygdal is not in the list.
You may want to look into the Python3 standard runtime, though it is in beta. It allows you to install arbitrary third-party libraries.
Modifying this links' answer I managed to get GDAL working in App Engine Flexible.
My dockerfile:
FROM gcr.io/google-appengine/python
RUN apt-get update && apt-get -y install libproj-dev libgdal-dev
RUN export CPLUS_INCLUDE_PATH=/usr/include/gdal
RUN export C_INCLUDE_PATH=/usr/include/gdal
RUN gdal-config --version
# Create a virtualenv for dependencies. This isolates these packages from
# system-level packages.
RUN virtualenv /env -p python2.7
# Setting these environment variables are the same as running
# source /env/bin/activate.
ENV VIRTUAL_ENV /env
ENV PATH /env/bin:$PATH
# Copy the application's requirements.txt and run pip to install all
# dependencies into the virtualenv.
ADD requirements.txt requirements.txt
RUN pip install -r requirements.txt
# Add the application source code.
ADD . /app
CMD gunicorn -t 120 -b :$PORT main:app
My app.yaml-file:
runtime: custom
env: flex
entrypoint: gunicorn -t 120 -b :$PORT main:app
endpoints_api_service:
name: xxxxx.com
rollout_strategy: managed
beta_settings:
cloud_sql_instances: project:europe-north1:dbinstance
runtime_config:
python_version: 2
requirements.text-file:
pygdal==1.11.3.3

docker-compose not downloading additions to requirements.txt file

I have a Django project running in docker.
When I add some packages to my requirments.txt file, they don't get downloaded when I run docker-compose up
Here is the relevant commands from my Dockerfile:
ADD ./evdc/requirements.txt /opt/evdc-venv/
ADD ./env-requirements.txt /opt/evdc-venv/
# Active venv
RUN . /opt/evdc-venv/bin/activate && pip install -r /opt/evdc- venv/requirements.txt
RUN . /opt/evdc-venv/bin/activate && pip install -r /opt/evdc-venv/env-requirements.txt
It seems docker is using a cached version of my requirements.txt file, as when I shell into the container, the requirements.txt file in /opt/evdc-venv/requirements.txt does not include the new packages.
Is there some way I can delete this cached version of requirements.txt?
Dev OS: Windows 10
Docker: 17.03.0-ce
docker-compose: 1.11.2
docker-compose up doesn't build a new image unless you have the build section defined with your Dockerfile and you pass it the --build parameter. Without that, it will reuse the existing image.
If your docker-compose.yml does not include the build section, and your build your images with docker build ..., then after you recreate your image, a docker-compose up will recreate the impacted containers.

How to get Django 1.7 working on Ubuntu 14.04 with nginx and virtualenv using python 2.7 while having python 3.4 installed?

I am a newbie to Django and Python installation. Intermediate with Ubuntu 14.04.
These are my installations so far in my Ubuntu 14.04.
apt-get install python3-setuptools --force-yes -y ## for python3
easy_install3 pip ## for python3
apt-get install python-setuptools --force-yes -y ## for python2.7 or above
easy_install pip ## for python2.7 or above
apt-get install python-dev --force-yes -y ## because ubuntu 14.04 does not have dev version of python 2
apt-get install python3-dev --force-yes -y ## because ubuntu 14.04 does not have dev version of python 3.4
apt-get install links --force-yes -y ##a command line web browser
apt-get install python-flup --force-yes -y ## connects python to uwsgi)
apt-get install build-essential --force-yes -y ##
pip2 install django uwsgi virtualenv ## use pip to install django and uwsgi and virtualenv for python2
pip3 install django uwsgi ## use pip to install django and uwsgi for python3
For the full list, please look at https://gist.github.com/simkimsia/41c55e0c08eda42e2cb3#file-install-sh-L88
I am confused about the use of virtualenv.
I want to prepare my ubuntu 14.04 server edition for a production level of Django 1.7 as much as possible.
The reason why I installed multiple Python environment because I may have other Python apps running which require 3.4.
My Django files are from bitbucket repository and I have git cloned them into /var/virtual/WebApps/DjangoProject
Inside /var/virtual/WebApps/DjangoProject, I have manage.py and other files and folders.
Please advise on how do I get the Django project running for this situation.
I am currently testing this setup on my virtualbox and vagrant.
EDIT
There will be at least 2 Django applications. 1 requires 2.7 python. The other requires 3.4 python.
Let me add that this is a single server that will host the application, frontend, and database.
EDIT 1
I have restarted with a fresh install of Ubuntu 14.04 and I started with Python 2.7.6 and Python 3.4.0.
I then did sudo apt-get install python-virtualenv which I checked its version: 1.11.4.
I have created ~/virtualenvs/py2.7 and ~/virtualenvs/py3.4.
Inside ~/virtualenvs, I did virtualenv -p /usr/bin/python2 py2.7
and ~/virtualenvs, I did virtualenv -p /usr/bin/python3 py3.4
So how do I install python2 only libraries for the python 2 app?
E.g. are django-adminfiles, sorl-thumbnail, psycopg2
EDIT 5
Use virtualenv --system-site-packages -p /usr/bin/python2 py2.7 instead
I have restarted with a fresh install of Ubuntu 14.04 and I started
with Python 2.7.6 and Python 3.4.0.
Okay, so now in your system you have two base versions of Python. Base version just means, the versions that are supported by your operating system; which you have installed globally.
In other words you have installed them using the operating system's package installers and did not compile them separately.
In practice, this above only matters in Linux, because in Windows you cannot install "locally" without going through a few hoops; all Python installers will register themselves in the registry thus making them global, base Python versions.
I then did sudo apt-get install python-virtualenv which I checked its
version: 1.11.4.
This package is outdated (current version is 12.0.7).
Now you have virtual environment installed against the base Python 2 version because the package requires Python 2.
In practical terms it means if you need to upgrade Python 2, you'll have to make sure python-virtualenv is also updated for the base versions of both Pythons that are supported by your operating system. This means, when you apt-get update and apt-get upgrade, virtualenv will be upgraded.
Usually this doesn't matter as its a rare case if python2 is upgraded and then python-virtualenv is not upgraded to match its dependency.
However this is not recommended because you want to control the versions of critical software "manually" to avoid any surprises. There are ways to control this on Ubuntu and other debian-like distributions by pinning versions; but even if you do so, you may not be getting the latest version of the library which may force you later on to uninstall the version that came with your operating system, and reinstall it from source.
I have created ~/virtualenvs/py2.7 and ~/virtualenvs/py3.4.
Inside ~/virtualenvs, I did virtualenv -p /usr/bin/python2 py2.7 and
~/virtualenvs, I did virtualenv -p /usr/bin/python3 py3.4
So how do I install python2 only libraries for the python 2 app?
E.g. are django-adminfiles, sorl-thumbnail, psycopg2
In order for solr-thumbnail and psycopg2 to be installed correctly, you need to build their dependencies; so
sudo apt-get install libjpeg62 libjpeg62-dev zlib1g-dev
sudo apt-get install libgraphicsmagick++-dev libboost-python1.55-dev
sudo apt-get install libexpat1-dev libpython-dev libpython3-dev libssl-dev libpq-dev
To install libraries for the Python 2 app:
Activate the virtual environment; by typing source ~/virtualenvs/py2.7/bin/activate
Type pip install _____ (name of the library)
To support multiple Python applications with different major versions; your system should have both Python major versions installed (you already have done this).
You then install virtualenv for each Python major version. You can skip this step if your applications are fully contained (that is, they include the Python runtime required - but this is a rare case) or if you have a single purpose server.
You should avoid installing anything but the base Python libraries in your system's global python. That is avoid (as root, or using sudo) to pip install things; because these will be installed for all users of Python and may cause problems (on some systems; like Fedora/RedHat - critical system packages like yum rely on the base system Python).
Next step is to make sure you have a suitable build environment available. This means for Debian-sourced systems to install build-essential and further the support libraries for common Python drivers and modules. The exact libraries you need to install will depend on the applications you are planning to host, but at a minimum you should make sure PIL (or Pillow) can be installed and database drivers' support libraries are available. To do so, you can apt-get build-deb python-imaging psycopg2 python-mysqldb (for PostgreSQL, MySQL and PIL).
Now you have a system ready to support most Python applications. You can then optionally add other utilities, but I would try to avoid assuming too much about what applications will require.
To host an app:
Create a virtual environment with the base version of Python required. So virtualenv-2.7 or virtualenv-3 as the normal non-root user account.
Install required packages into the virtual environment.
Adjust the bootstrap script for your application to use the correct Python binary. This is usually done from whatever process you are using to manage your application server. For example, on my server I use supervisord.
That's all you have to do. Everything else will depend on the individual application's requirements and setup (so if you need to serve static files, you'll have to configure that mapping, etc.)
After reading your shell script, it seems you are trying to build a server that will support both the application, the front end and the database.
In order to support such a system; you will need to install the following:
Database server(s) that you would like to support. As this is a single purpose server, you will also need to install database command line clients.
Source code tools (git, etc.)
A global process manager (like supervisor or circus).
Base Python versions you intend to support; and their development headers (sudo apt-get install python-dev)
setuptools, pip, and then virtualenv. These tools should be installed from source rather than your package manager; to ensure the latest versions are installed. You should install these globally (ie, as root) so they are available for all users.
A build tool chain (ie, "Development Tools" or build-essential)
Support libraries for any extensions (but not the extensions themselves). The easiest way to do this is to use the package manager to build the dependencies and not the packages sudo apt-get build-dep python-imaging psycopg2 python-mysqldb.
The next thing you need to do is decide how you will run your application servers (the "django code"). You can use uwsgi, gunicorn, etc. as these are the ones most tested with django.
You need to be able to support multiple versions of these runtimes, so instead of installing them globally across the system; just build their dependencies and install the specific version required for each application in its own isolated environment.
The next thing you need to install is a front end proxy for your applications. You can install whatever proxy suits your needs (nginx is the most popular); but please install from source rather than the packages as those are almost always out of date.
Once all this is setup, the process of hosting a django application is the following:
Create a separate user account with a non-login shell.
Create a virtual environment in this user's home directory. I recommend keeping some standard here, like env for the virtual environments.
Download/copy the source code of your application.
Create a standard directory where you will store the static files. For example I use $HOME/www/static.
Create an entry in your process manager.
Create an entry in your proxy for front end routing.
Reload your proxy server.
Reload your process manager.
You can automate/script a lot of the above. For example, you can create a custom skeleton directory to create the base directories for you when adding new users; and you can create custom templates for other areas using tools like cookiecutter.
Understanding execution path
The first principle to understand is that when you install packages on your operating system (virtual machine, whatever) with sudo is that you are installing all those packages in a global location, that is, a file directory which your system knows about via the $PATH (PATH) environment variable.
This $PATH variable is often set-up by default in your .bashrc or your .bash_profile or your .profile whenever a new linux/unix user is created. Whether you have any of these files depends on what is inside the /etc/skel on your system. /etc/skel holds a "template" of these files that gets duplicated whenever a new user with a home directory is created.
When you type echo $PATH in command line, you would see a list of execution search path delimited by :, for example:
/usr/local/sbin:/usr/local/bin:/usr/bin
This is an example I will use for the purpose of this discussion. Different OS will give you slightly different default $PATH but the simple idea here is that the binaries of your globally installed packages gets thrown into one of these directories and the reason you are able to run these binaries is because these binaries (programs) are now available in the execution search path (simply called $PATH).
Ok great, but what does this mean for the python 2 and python 3 interpreters I installed?
So in relation to your question, this means that when you sudo apt-get or sudo aptitude install python2 or python3 binaries (python interpreters), they are both available and to differentiate which interpeter you are using at any moment, you would run python2.7 or python3.4 that correspondingly calls /usr/bin/python2.7 or /usr/bin/python3.4
You can always check this easily by using the which linux/unix command. which python3.4 will return you the exact path where your python3.4 binary is installed.
Similarly, when type pip2.7 in your command line, you are asking your system to execute the pip2.7 program that came installed with your python2.7 package. And naturally which pip2.7 will reveal to you where this pip2.7 binary has been installed.
All this is possible simply because these binaries are have been installed by you using sudo apt-get and are placed in the directories listed in $PATH. If you move one of these binaries forcibly to another directory not listed in $PATH, you will realize that you can no longer run the binary in your command line without typing out the specific path to the binary.
Additional python specific information
The Python Interpreter has another attribute call $PYTHONPATH. This - as you will rightly deduce - is a variable that holds a list of directories ("search path") where the python interpreter will search for python modules to load. If you want to know where your python interpreter is currently looking for modules (your own python modules or 3rd party python modules), run
python -c "import sys; print(sys.path)"
where python is your specific python interpreter. If /usr/bin/python is symlinked to /usr/bin/python2.7, then you are in fact calling python2.7.
When would python path matter? It matters inside your own .py source code when you ask to import other modules. The import line of code in your .py source code is where you are asking the python interpreter to go forth and search for the module that you want to import. As you can imagine, if your sys.path (in python) is empty, you will not be able to import any 3rd party modules.
Beyond the gory details
Now that we have a clear understanding of the underlying principles behind $PATH and $PYTHONPATH, we can now understand what the virtualenv (and additionally, virtualenvwrapper is useful) does for us.
When we create a new virtualenv giving it a directory, what we are saying is that we want to symlink a specific python interpreter (via -p python2.7 flag for the virtualenv command) for example to that virtualenv.
When we source activate that virtualenv we created, we are in fact invoking shell scripts that come with virtualenv to dynamically modify the $PATH. Try running echo $PATH after you have source activated a virtualenv you created. What do you see?
That's right, you will be seeing something like this:-
/Users/calvin/.virtualenvs/myproject/bin:/usr/local/sbin:/usr/local/bin:/usr/bin
And if you type which python, what do you get?
/Users/calvin/.virtualenvs/myproject/bin/python
That's right, the python interpreter we are using is the one that is inside the virtualenv directory and no longer from the /usr/bin directory.
If you run
ls -la /Users/calvin/.virtualenvs/myproject/bin
what do you see?
Ah! A symlink to the specific global python interpreter you specified when you created this virtualenv. If you don't see a symlink, this means that your entire python interpreter was copied over from the globally installed one.
So this is what our virtualenv tool does. It lets us isolate specific projects and choose which python interpreter to use for a specific project.
Once you have source activated a virtualenv, your pip is also the pip that is located in your virtualenv directory. This pip is python path-aware. When you issue pip install commands, python packages now gets installed into your
/Users/calvin/.virtualenvs/myproject/lib/site-packages
python packages directory; and are available ONLY to your project when you source activate that particular project.
What if you install packages with sudo pip?
sudo pip calls the pip tool that comes with your globally installed python interpreter. When you use sudo pip, you are installing your python packages into a global location (which is not jailed within a virtualenv).
I did not give you specific answers to your how-can-I-make-two-projects-use-two-different-python-interpreters question. I explained the principles and now that you know the principles, it is clear what you need to do. Cheers!
:D
you should have to try following steps to make your django work with python-2.7.
As Ubuntu-14 already come with Python-2.7 installed. so no need to install python-2.7.
First of all install python setuptools for python-2.7:
https://pypi.python.org/packages/source/s/setuptools/setuptools-12.0.5.tar.gz
tar -zxvf setuptools-12.0.5.tar.gz
cd setuptools-12.0.5/
sudo python2.7 setup.py install
after install setuptools install pip for python-2.7
wget https://pypi.python.org/packages/source/p/pip/pip-6.0.8.tar.gz
tar -zxvf pip-6.0.8.tar.gz
cd pip-6.0.8/
sudu python2.7 setup.py install
after installing pip now we have to go for install python virtual environment:
sudo pip2.7 install virtualenv
then to folder where you want to create new virtualenv using python 2.7
virtualenv-2.7 "name for new virtualenv for example '/var/virtual/DjangoProject'"
cd /var/virtual/
virtualenv-2.7 DjangoProject
Note just created virtualenv name is "DjangoProject"
Now time to activate new virtualenv
cd DjangoProject
source bib/activate
Now time to clone your project here.
git clone "your git url"
install rest of apps and django here. if you have created simply install by requirement.txt
cd "projectFolder"
pip install -r requirement.txt
after doing all these your new python2.7 django with virtualenv are ready to use. just run django wsgi server for test is every thing working:
python manage.py runserver.
Now you can use this virtualenv and project to setup for web server.
Hope this will help-full to you.
You should use pyenv (and pyenv virtualenvwrapper). With these tools you can have multiple Python versions and switch between them.
Here is how you setup one environment with Python 3.4.2 and one with Python 2.7.8 (and each environment can have its own Python packages)
# install pyenv
git clone https://github.com/yyuu/pyenv.git ~/.pyenv
# setup pyenv and load when shell is loaded
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init -)"' >> ~/.bashrc
# install pyenv virtualenvwrapper
git clone https://github.com/yyuu/pyenv-virtualenvwrapper.git ~/.pyenv/plugins/pyenv-virtualenvwrapper
# setup pyenv virtualenvwrapper and load when shell is loaded
echo 'export PYENV_VIRTUALENVWRAPPER_PREFER_PYVENV="true"' >> ~/.bashrc
echo "pyenv virtualenvwrapper" >> ~/.bashrc
Now everything is setup. Restart your shell.
# install python 2.7.8
pyenv install 2.7.8
pyenv rehash
# install python 3.4.2
pyenv install 3.4.2
pyenv rehash
# switch the global python version to 2.7.8
pyenv global 2.7.8
# create a virtual environment using python 2.7.8
mkvirtualenv project278
# -- now you can install you python 2 modules
# leave the virtual environment
deactivate
# switch the global python to 3.4.2
pyenv global 3.4.2
# create a virtual environment using python 3.4.2
mkvirtualenv project342
# -- now you can install you python 2 modules
# leave the virtual environment
deactivate
# switch the global python to the system python.
pyenv global system
# swith to environment project278 and check the python version
workon project278
python --version
# swith to environment project342 and check the python version
workon project342
python --version
VoilĂ ! You now have two environments with different Python versions. Just use the workon (and the deactivate) commands to switch between them.
Make sure you read the documentation of the used packages, so you understand what is going on!