Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(gunicorn): Updated image to use gunicorn and new base image #1121

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ ENV/
.mypy_cache/

# jwt keys
keys
tests/resources/keys/*.pem

.DS_Store
Expand Down
111 changes: 59 additions & 52 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,56 +1,63 @@
# To run: docker run --rm -d -v /path/to/fence-config.yaml:/var/www/fence/fence-config.yaml --name=fence -p 80:80 fence
# To check running container do: docker exec -it fence /bin/bash
ARG AZLINUX_BASE_VERSION=master

FROM quay.io/cdis/python:python3.9-buster-2.0.0
# Base stage with python-build-base
FROM quay.io/cdis/python-build-base:${AZLINUX_BASE_VERSION} as base

# Comment this in, and comment out the line above, if quay is down
# FROM 707767160287.dkr.ecr.us-east-1.amazonaws.com/gen3/python-build-base:${AZLINUX_BASE_VERSION} as base

ENV appname=fence
ENV POETRY_NO_INTERACTION=1 \
POETRY_VIRTUALENVS_IN_PROJECT=1 \
POETRY_VIRTUALENVS_CREATE=1

WORKDIR /${appname}

# create gen3 user
# Create a group 'gen3' with GID 1000 and a user 'gen3' with UID 1000
RUN groupadd -g 1000 gen3 && \
useradd -m -s /bin/bash -u 1000 -g gen3 gen3 && \
chown -R gen3:gen3 /$appname && \
chown -R gen3:gen3 /venv


# Builder stage
FROM base as builder

USER gen3


RUN python -m venv /venv

COPY poetry.lock pyproject.toml /${appname}/

RUN pip install poetry && \
poetry install -vv --only main --no-interaction

COPY --chown=gen3:gen3 . /$appname
COPY --chown=gen3:gen3 ./deployment/wsgi/wsgi.py /$appname/wsgi.py

# Run poetry again so this app itself gets installed too
RUN poetry install --without dev --no-interaction

RUN git config --global --add safe.directory /${appname} && COMMIT=`git rev-parse HEAD` && echo "COMMIT=\"${COMMIT}\"" > /$appname/version_data.py \
&& VERSION=`git describe --always --tags` && echo "VERSION=\"${VERSION}\"" >> /$appname/version_data.py

# Final stage
FROM base

COPY --from=builder /venv /venv
COPY --from=builder /$appname /$appname

# install tar
RUN yum install tar -y

# Switch to non-root user 'gen3' for the serving process
USER gen3

RUN source /venv/bin/activate

ENV PYTHONUNBUFFERED=1 \
PYTHONIOENCODING=UTF-8

RUN pip install --upgrade pip
RUN pip install --upgrade poetry
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl bash git \
&& apt-get -y install vim \
libmcrypt4 mcrypt \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/

RUN mkdir -p /var/www/$appname \
&& mkdir -p /var/www/.cache/Python-Eggs/ \
&& mkdir /run/nginx/ \
&& ln -sf /dev/stdout /var/log/nginx/access.log \
&& ln -sf /dev/stderr /var/log/nginx/error.log \
&& chown nginx -R /var/www/.cache/Python-Eggs/ \
&& chown nginx /var/www/$appname

# aws cli v2 - needed for storing files in s3 during usersync k8s job
RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
&& unzip awscliv2.zip \
&& ./aws/install \
&& /bin/rm -rf awscliv2.zip ./aws

WORKDIR /$appname

# copy ONLY poetry artifact, install the dependencies but not fence
# this will make sure than the dependencies is cached
COPY poetry.lock pyproject.toml /$appname/
RUN poetry config virtualenvs.create false \
&& poetry install -vv --no-root --no-dev --no-interaction \
&& poetry show -v

# copy source code ONLY after installing dependencies
COPY . /$appname
COPY ./deployment/uwsgi/uwsgi.ini /etc/uwsgi/uwsgi.ini
COPY ./deployment/uwsgi/wsgi.py /$appname/wsgi.py
COPY clear_prometheus_multiproc /$appname/clear_prometheus_multiproc

# install fence
RUN poetry config virtualenvs.create false \
&& poetry install -vv --no-dev --no-interaction \
&& poetry show -v

RUN COMMIT=`git rev-parse HEAD` && echo "COMMIT=\"${COMMIT}\"" >$appname/version_data.py \
&& VERSION=`git describe --always --tags` && echo "VERSION=\"${VERSION}\"" >>$appname/version_data.py

WORKDIR /var/www/$appname

CMD ["sh","-c","bash /fence/dockerrun.bash && /dockerrun.sh"]
CMD ["gunicorn", "-c", "deployment/wsgi/gunicorn.conf.py"]
37 changes: 0 additions & 37 deletions deployment/uwsgi/uwsgi.ini

This file was deleted.

9 changes: 9 additions & 0 deletions deployment/wsgi/gunicorn.conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
wsgi_app = "deployment.wsgi.wsgi:application"
bind = "0.0.0.0:8000"
workers = 4
preload_app = True
user = "gen3"
group = "gen3"
timeout = 300
keepalive = 2
keepalive_timeout = 5
File renamed without changes.
5 changes: 4 additions & 1 deletion dockerrun.bash
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Update certificate authority index -
# environment may have mounted more authorities
#
update-ca-certificates
# update-ca-certificates
#
# Kubernetes may mount jwt-keys as a tar ball
#
Expand All @@ -15,6 +15,9 @@ if [ -f /fence/jwt-keys.tar ]; then
if [ -d jwt-keys ]; then
mkdir -p keys
mv jwt-keys/* keys/
rm -rf /fence/keys/key/
fi
)
fi

gunicorn -c /fence/deployment/wsgi/gunicorn.conf.py
21 changes: 17 additions & 4 deletions fence/jwt/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,26 @@ def from_directory(cls, keys_dir, naming_function=None):
prv_filepath = os.path.join(keys_dir, "jwt_private_key.pem")

if not os.path.isfile(pub_filepath):
raise EnvironmentError(
"missing public key file; expected file to exist: " + pub_filepath
)
# Generate public key from private key
with open(prv_filepath, "r") as f:
private_key_file = f.read()
private_key = serialization.load_pem_private_key(
bytes(private_key_file, "utf-8"),
password=None,
backend=default_backend(),
)
public_key = private_key.public_key()
public_key = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo,
)
public_key = public_key.decode("utf-8")
with open(pub_filepath, "w") as f:
f.write(public_key)

if not os.path.isfile(prv_filepath):
raise EnvironmentError(
"missing public key file; expected file to exist: " + prv_filepath
"missing private key file; expected file to exist: " + prv_filepath
)

with open(pub_filepath, "r") as f:
Expand Down
1 change: 1 addition & 0 deletions keys/key/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Need this folder for permission reasons inside the container
Loading
Loading