Skip to content

Commit cb29895

Browse files
Dockerfile for creating Python-oracledb application development
environment container.
1 parent 065bbf9 commit cb29895

File tree

19 files changed

+1240
-2
lines changed

19 files changed

+1240
-2
lines changed

doc/src/release_notes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ Common Changes
107107
#) Error ``DPY-2056: registered handler for protocol "{protocol}" failed for
108108
arg "{arg}"`` is now raised when an exception occurs when calling the
109109
registered handler for a protocol.
110+
#) Added a sample Dockerfile that can be used to create a container for
111+
developing and deploying python-oracledb applications.
110112
#) Internal change: improve handling of metadata.
111113
#) Internal build tool change: bumped minimum Cython version to 3.0.10 to
112114
avoid bug in earlier versions.
Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
# -----------------------------------------------------------------------------
2+
# Copyright (c) 2025 Oracle and/or its affiliates.
3+
#
4+
# This software is dual-licensed to you under the Universal Permissive License
5+
# (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
6+
# 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
7+
# either license.
8+
#
9+
# If you elect to accept the software under the Apache License, Version 2.0,
10+
# the following applies:
11+
#
12+
# Licensed under the Apache License, Version 2.0 (the "License");
13+
# you may not use this file except in compliance with the License.
14+
# You may obtain a copy of the License at
15+
#
16+
# https://www.apache.org/licenses/LICENSE-2.0
17+
#
18+
# Unless required by applicable law or agreed to in writing, software
19+
# distributed under the License is distributed on an "AS IS" BASIS,
20+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21+
# See the License for the specific language governing permissions and
22+
# limitations under the License.
23+
# -----------------------------------------------------------------------------
24+
#
25+
# NAME
26+
#
27+
# Dockerfile
28+
#
29+
# PURPOSE
30+
#
31+
# Sample Dockerfile that creates a container image for Python application
32+
# development and application deployment. The container has python-oracledb
33+
# installed, the Apache web server with WSGI, and (optionally) Oracle Instant
34+
# Client pre-configured.
35+
#
36+
# The container is for testing and development purposes only.
37+
#
38+
# NOTE
39+
#
40+
# Read README.md and then use container_build.sh to build the container from
41+
# this Dockerfile
42+
#
43+
44+
# Variable declaration for base OS
45+
# --------------------------------
46+
ARG OPY_OS_VERSION=8
47+
48+
# Base OS container image details
49+
# -------------------------------
50+
FROM ghcr.io/oracle/oraclelinux:${OPY_OS_VERSION} AS baseos
51+
52+
# OS Username
53+
ARG OPY_USERNAME
54+
55+
# OS Username's Groupname
56+
ARG OPY_GROUPNAME
57+
58+
# Python Version details
59+
ARG OPY_PYTHON_VERSION
60+
61+
# Instant Client Details
62+
ARG OPY_INSTANT_CLIENT_VERSION
63+
64+
# User base directory
65+
ARG OPY_BASEDIR=/opt
66+
67+
# OS User home directory
68+
ARG OPY_OS_USER_HOMEDIR=/home/${OPY_USERNAME}
69+
70+
# Virtual environment directory name
71+
ARG OPY_PYTHON_VIRTUAL_DIRNAME=pyorcldb_env
72+
73+
# OS Version
74+
ARG OPY_OS_VERSION=8
75+
76+
RUN dnf upgrade && \
77+
# Install latest Instant Client 23ai
78+
( ( [ ${OPY_INSTANT_CLIENT_VERSION} == 23 ] && \
79+
dnf install oracle-instantclient-release-23ai-el${OPY_OS_VERSION} && \
80+
dnf install oracle-instantclient-basic \
81+
oracle-instantclient-sqlplus ) || \
82+
# Install latest Instant Client 21c
83+
( [ ${OPY_INSTANT_CLIENT_VERSION} == 21 ] && \
84+
dnf install oracle-instantclient-release-el${OPY_OS_VERSION} && \
85+
dnf install oracle-instantclient-basic \
86+
oracle-instantclient-sqlplus ) || \
87+
( [ ${OPY_INSTANT_CLIENT_VERSION} == None ] && \
88+
echo "Not installing Instant Client" ) || \
89+
# Install specific Instant Client 19c release update
90+
( \
91+
# Install Instant Client 19c on Oracle Linux 9
92+
( ( [ ${OPY_OS_VERSION} == 9 ] && \
93+
dnf install oracle-instantclient-release-el${OPY_OS_VERSION} && \
94+
dnf install \
95+
oracle-instantclient${OPY_INSTANT_CLIENT_VERSION}-basic \
96+
oracle-instantclient${OPY_INSTANT_CLIENT_VERSION}-sqlplus \
97+
) || \
98+
# Install Instant Client 19c on Oracle Linux 8
99+
( dnf install oracle-release-el${OPY_OS_VERSION} && \
100+
dnf install \
101+
oracle-instantclient${OPY_INSTANT_CLIENT_VERSION}-basic \
102+
oracle-instantclient${OPY_INSTANT_CLIENT_VERSION}-sqlplus \
103+
) ) ) || \
104+
( echo "Not installing Instant Client" ) \
105+
) && \
106+
# Install sudo, openssl and Python
107+
# Installing ncurses to include 'clear' command
108+
dnf install sudo openssl apr apr-util ncurses && \
109+
echo "Python Version - ${OPY_PYTHON_VERSION}" && \
110+
dnf install python${OPY_PYTHON_VERSION} python${OPY_PYTHON_VERSION}-pip \
111+
python${OPY_PYTHON_VERSION}-devel && \
112+
( ( [ ${OPY_OS_VERSION} == 9 ] && \
113+
update-alternatives --install /usr/bin/python python \
114+
/usr/bin/python${OPY_PYTHON_VERSION} 1 ) || \
115+
( echo "Not required to set Python default" ) \
116+
) && \
117+
# Add OS user
118+
useradd -U -d ${OPY_OS_USER_HOMEDIR} ${OPY_USERNAME} && \
119+
# Enable sudo access for appuser
120+
echo "%appuser ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \
121+
# Create required directories
122+
mkdir ${OPY_BASEDIR}/downloads && \
123+
chown ${OPY_USERNAME}:${OPY_GROUPNAME} ${OPY_BASEDIR}/downloads && \
124+
mkdir ${OPY_BASEDIR}/wallet && \
125+
chown ${OPY_USERNAME}:${OPY_GROUPNAME} ${OPY_BASEDIR}/wallet && \
126+
mkdir ${OPY_BASEDIR}/apache && \
127+
chown ${OPY_USERNAME}:${OPY_GROUPNAME} ${OPY_BASEDIR}/apache && \
128+
mkdir ${OPY_BASEDIR}/${OPY_PYTHON_VIRTUAL_DIRNAME} && \
129+
chown ${OPY_USERNAME}:${OPY_GROUPNAME} \
130+
${OPY_BASEDIR}/${OPY_PYTHON_VIRTUAL_DIRNAME} && \
131+
mkdir ${OPY_BASEDIR}/app && \
132+
chown ${OPY_USERNAME}:${OPY_GROUPNAME} ${OPY_BASEDIR}/app && \
133+
mkdir ${OPY_BASEDIR}/cert && \
134+
chown ${OPY_USERNAME}:${OPY_GROUPNAME} ${OPY_BASEDIR}/cert && \
135+
# Clean up cache
136+
dnf clean all
137+
138+
FROM baseos AS pythonenv
139+
140+
# OS Username
141+
ARG OPY_USERNAME
142+
143+
# OS Username's Groupname
144+
ARG OPY_GROUPNAME
145+
146+
# Python Version details
147+
ARG OPY_PYTHON_VERSION
148+
149+
# Virtual environment directory name
150+
ARG OPY_PYTHON_VIRTUAL_DIRNAME=pyorcldb_env
151+
152+
# User base directory
153+
ARG OPY_BASEDIR=/opt
154+
155+
# OS User home directory
156+
ARG OPY_OS_USER_HOMEDIR=/home/${OPY_USERNAME}
157+
158+
# Switch User
159+
USER ${OPY_USERNAME}
160+
161+
# Copy Auto deploy script template
162+
COPY --chown=${OPY_USERNAME}:${OPY_GROUPNAME} \
163+
otherfiles/autodeployscript.sh.template \
164+
${OPY_OS_USER_HOMEDIR}/autodeployscript.sh
165+
166+
# Configure virtual environment
167+
RUN cd ${OPY_BASEDIR} && \
168+
python${OPY_PYTHON_VERSION} -m venv ${OPY_PYTHON_VIRTUAL_DIRNAME} && \
169+
# Source the Python virtual environment
170+
source ${OPY_BASEDIR}/${OPY_PYTHON_VIRTUAL_DIRNAME}/bin/activate && \
171+
# Upgrade pip utility
172+
python -m pip install --upgrade pip && \
173+
# Install python-oracledb driver for Python
174+
# Install wheel module (pre-requisite for WSGI module)
175+
python -m pip install oracledb wheel && \
176+
# Configure PATH and set the Python virtual environment user profile
177+
echo "export PATH=${OPY_BASEDIR}/apache/bin:\$PATH" >> \
178+
${OPY_OS_USER_HOMEDIR}/.bashrc && \
179+
echo "source ${OPY_BASEDIR}/${OPY_PYTHON_VIRTUAL_DIRNAME}/bin/activate" >> \
180+
${OPY_OS_USER_HOMEDIR}/.bashrc && \
181+
echo "if [ ! -f ${OPY_BASEDIR}/cert/certificate.pem ]; then" >> \
182+
${OPY_OS_USER_HOMEDIR}/.bashrc && \
183+
echo " ~/pyorcldb_generate_cert.sh" >> ${OPY_OS_USER_HOMEDIR}/.bashrc && \
184+
echo "fi" >> ${OPY_OS_USER_HOMEDIR}/.bashrc && \
185+
echo "~/autodeployscript.sh" >> ${OPY_OS_USER_HOMEDIR}/.bashrc && \
186+
echo "" >> ${OPY_OS_USER_HOMEDIR}/.bashrc && \
187+
sed -i "s/OPY_OSUSERBASEDIR/\\${OPY_BASEDIR}/g" \
188+
${OPY_OS_USER_HOMEDIR}/autodeployscript.sh
189+
190+
# Intermediate image for building Apache Server
191+
# ---------------------------------------------
192+
FROM pythonenv AS apachebuildenv
193+
194+
# Variables declaration for ApacheBuildEnv
195+
# ----------------------------------------
196+
197+
# Apache Server Configuration - Version
198+
ARG OPY_APACHE_SERVER_VERSION
199+
200+
# Python Version details
201+
ARG OPY_PYTHON_VERSION
202+
ARG OPY_PYTHON_VERSION_WITHOUTPERIOD
203+
204+
# OS Username
205+
ARG OPY_USERNAME
206+
207+
# OS Username's Groupname
208+
ARG OPY_GROUPNAME
209+
210+
# Virtual environment directory name
211+
ARG OPY_PYTHON_VIRTUAL_DIRNAME=pyorcldb_env
212+
213+
# User base directory
214+
ARG OPY_BASEDIR=/opt
215+
216+
# Apache HTTP Server Listen port number
217+
ARG OPY_APACHE_LISTEN_PORT
218+
219+
# Switch username
220+
USER ${OPY_USERNAME}
221+
222+
# Copy Apache WSGI configuration file template into downloads directory
223+
COPY --chown=${OPY_USERNAME}:${OPY_GROUPNAME} \
224+
otherfiles/pyorcldb_wsgi.conf.template ${OPY_BASEDIR}/downloads
225+
226+
# Install Apache Server
227+
RUN sudo dnf install \
228+
# Install prerequisite packages for Apache installation
229+
gcc make expat-devel pcre-devel apr-devel apr-util-devel \
230+
redhat-rpm-config openssl-devel perl && \
231+
# Download Apache server source
232+
cd ${OPY_BASEDIR}/downloads && \
233+
curl -o ${OPY_APACHE_SERVER_VERSION}.tar.gz \
234+
"https://archive.apache.org/dist/httpd/${OPY_APACHE_SERVER_VERSION}.tar.gz" && \
235+
tar xzvf ${OPY_APACHE_SERVER_VERSION}.tar.gz && \
236+
cd ${OPY_APACHE_SERVER_VERSION} && \
237+
# Prepare and install Apache server
238+
./configure --enable-ssl --prefix=${OPY_BASEDIR}/apache && \
239+
make && \
240+
make install && \
241+
# Set path of the Perl in Apache's apxs utility. This is required for
242+
# building wsgi_mod.
243+
sed -i "s/\/replace\/with\/path\/to\/perl\/interpreter/\/usr\/bin\/perl/g" \
244+
${OPY_BASEDIR}/apache/bin/apxs && \
245+
export PATH=${OPY_BASEDIR}/apache/bin:$PATH && \
246+
source ${OPY_BASEDIR}/${OPY_PYTHON_VIRTUAL_DIRNAME}/bin/activate &&\
247+
# Install WSGI module
248+
python -m pip install mod_wsgi && \
249+
# Copy the mod_wsgi module from python virtual environment to Apache home
250+
cp ${OPY_BASEDIR}/${OPY_PYTHON_VIRTUAL_DIRNAME}/lib/python${OPY_PYTHON_VERSION}/site-packages/mod_wsgi/server/mod_wsgi-py${OPY_PYTHON_VERSION_WITHOUTPERIOD}.cpython-${OPY_PYTHON_VERSION_WITHOUTPERIOD}-x86_64-linux-gnu.so \
251+
${OPY_BASEDIR}/apache/modules/mod_wsgi.so && \
252+
# Configure httpd.conf
253+
# --------------------
254+
# 1. Removed listening on port 80
255+
# 2. Enabled SSL module
256+
# 3. Set default characterset to UTF-8
257+
cd ${OPY_BASEDIR}/apache/conf && \
258+
sed -i "s/Listen 80/# Listen 80/g" httpd.conf && \
259+
sed -i "s/#LoadModule ssl_module/LoadModule ssl_module/g" httpd.conf && \
260+
echo "AddDefaultCharset UTF-8" >> httpd.conf && \
261+
echo "Include conf/extra/pyorcldb_wsgi.conf" >> httpd.conf && \
262+
# Populate pyorcldb_wsgi.conf file into Apache's conf/extra directory
263+
cd ${OPY_BASEDIR}/apache/conf/extra && \
264+
cp ${OPY_BASEDIR}/downloads/pyorcldb_wsgi.conf.template \
265+
./pyorcldb_wsgi.conf && \
266+
sed -i "s/OPY_BASEDIR/\\${OPY_BASEDIR}/g" pyorcldb_wsgi.conf && \
267+
sed -i "s/OPY_PYTHONVIRTUALDIRNAME/${OPY_PYTHON_VIRTUAL_DIRNAME}/g" \
268+
pyorcldb_wsgi.conf && \
269+
sed -i "s/OPY_APACHE_LISTEN_PORT/${OPY_APACHE_LISTEN_PORT}/g" \
270+
pyorcldb_wsgi.conf && \
271+
rm ${OPY_BASEDIR}/downloads/pyorcldb_wsgi.conf.template && \
272+
# Clean all cached packages from DNF cache
273+
sudo dnf clean all && \
274+
# Clean all downloads directory
275+
cd ${OPY_BASEDIR}/downloads && \
276+
rm -rf *
277+
278+
# Python Development Image
279+
# ------------------------
280+
FROM pythonenv AS developmentimage
281+
282+
# OS Username
283+
ARG OPY_USERNAME
284+
285+
# OS Username's Groupname
286+
ARG OPY_GROUPNAME
287+
288+
# OS User home directory
289+
ARG OPY_OS_USER_HOMEDIR=/home/${OPY_USERNAME}
290+
291+
# User base directory
292+
ARG OPY_BASEDIR=/opt
293+
294+
# Image metadata details
295+
ARG OPY_IMAGE_VERSION
296+
ARG OPY_IMAGE_RELEASE_DATE
297+
ARG OPY_IMAGE_RELEASE_STATUS
298+
299+
# Image metadata
300+
# Uncomment the below lines to provide the label information
301+
# LABEL version=
302+
# LABEL release-date=
303+
# LABEL maintainer=
304+
# LABEL release-status=
305+
306+
# Switch to OS user from root
307+
# ---------------------------
308+
USER ${OPY_USERNAME}
309+
310+
WORKDIR ${OPY_OS_USER_HOMEDIR}
311+
312+
# Get Apache Server
313+
COPY --from=apachebuildenv --chown=${OPY_USERNAME}:${OPY_GROUPNAME} \
314+
${OPY_BASEDIR}/apache ${OPY_BASEDIR}/apache
315+
316+
# Copy SSL certificate generation script
317+
COPY --chown=${OPY_USERNAME}:${OPY_GROUPNAME} \
318+
otherfiles/pyorcldb_generate_cert.sh ${OPY_OS_USER_HOMEDIR}/

0 commit comments

Comments
 (0)