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

Refactoring/#258 used a non root user to run jupyter in the docker image ai lab #231

Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
7bacff9
Use separate user for running Jupyter
ckunki Feb 23, 2024
6663562
Used a non-root user to run Jupyter in the Docker Image ai-lab
ckunki Feb 26, 2024
194e9d1
Additional changes based on experiments
ckunki Feb 27, 2024
5befe3e
Fixed ansible tasks
ckunki Feb 27, 2024
1e510fc
remove commented line
ckunki Feb 27, 2024
69de9d8
Added become for disabling core dumps
ckunki Feb 27, 2024
d9eed17
poetry lock
ckunki Feb 27, 2024
af1a929
Fixed test
ckunki Feb 27, 2024
c776849
Improved Ansible output for pip install
ckunki Feb 27, 2024
36117ea
Improved Ansible output for pip install
ckunki Feb 27, 2024
5229b26
Merge branch 'main' into refactoring/#258-Used_a_non-root_user_to_run…
ckunki Feb 27, 2024
2304741
Removed test scaffolds
ckunki Feb 27, 2024
b030baf
Capitalized name of Ansible task
ckunki Feb 27, 2024
a66235d
Updated comments in Ansible tasks
ckunki Feb 27, 2024
71ecf25
Updated user guide for Docker Edition
ckunki Feb 27, 2024
514cdd0
Updated tests for docker Edition
ckunki Feb 27, 2024
50b4432
Increased time out for commiting the Docker container
ckunki Feb 27, 2024
b595ae6
Added comment for timeout
ckunki Feb 27, 2024
97b5635
Show name of docker container when keeping it alive
ckunki Feb 28, 2024
b8229da
Moved integration/test_create_dss_docker_image to codebuild
ckunki Feb 28, 2024
f347df9
[CodeBuild]
ckunki Feb 28, 2024
e0a0cae
Fixed import for ci tests
ckunki Feb 28, 2024
dc426ad
[CodeBuild]
ckunki Feb 28, 2024
c254cee
Updated dependencies to fix vulnerabilities
ckunki Feb 28, 2024
0235d4d
[CodeBuild]
ckunki Feb 28, 2024
92781ad
Added free disk space to workflows/check_ci.yaml
ckunki Feb 28, 2024
62004a3
Use user "jupyter" for EC2, too
ckunki Feb 28, 2024
3c19388
Updated documentation
ckunki Feb 28, 2024
d9d6205
[CodeBuild]
ckunki Feb 28, 2024
7ee7abf
Updated dependency network-manager
ckunki Feb 28, 2024
887d558
[CodeBuild]
ckunki Feb 28, 2024
8ace780
Fixed test test_jupyter_password_message_shown
ckunki Feb 28, 2024
427696b
Removed comment
ckunki Feb 28, 2024
3467495
Merge branch 'main' into refactoring/#258-Used_a_non-root_user_to_run…
ckunki Feb 28, 2024
524656a
Fixed review findings
ckunki Feb 28, 2024
dfb6b5e
Fixed review findings
ckunki Feb 28, 2024
0574c95
Update exasol/ds/sandbox/runtime/ansible/roles/jupyter/templates/etc/…
ckunki Feb 29, 2024
1778e81
Fixed review finding
ckunki Feb 29, 2024
b10fa2e
Fixed failing test
ckunki Feb 29, 2024
ab3b254
Merge branch 'main' into refactoring/#258-Used_a_non-root_user_to_run…
ckunki Feb 29, 2024
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
2 changes: 1 addition & 1 deletion doc/changes/changes_1.1.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ n/a
* #217: Changed notebook-connector dependency, now installing it from PyPi.
* #220: Changed default ports in the external database configuration.
* #221: Changed wording in the main configuration notebook, as suggested by PM.

* #66: Used a non-root user to run Jupyter in the Docker Image ai-lab
17 changes: 17 additions & 0 deletions exasol/ds/sandbox/lib/dss_docker/create_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ def _docker_file(self) -> importlib_resources.abc.Traversable:
def _start_container(self) -> DockerContainer:
self._start = datetime.now()
docker_client = docker.from_env()
try:
return docker_client.containers.get(self.container_name)
except:
pass
Comment on lines +117 to +120
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added these lines to speed up testing Ansible tasks

docker_file = self._docker_file()
_logger.info(f"Creating docker image {self.image_name} from {docker_file}")
if self.registry is not None:
Expand Down Expand Up @@ -157,6 +161,7 @@ def _commit_container(
notebook_folder_initial = get_fact(facts, "notebook_folder", "initial")
conf = {
"Entrypoint": entrypoint(facts),
"User": get_fact(facts, "jupyter", "user"),
"Cmd": [],
"Volumes": {notebook_folder_final: {}, },
"ExposedPorts": {f"{port}/tcp": {}},
Expand Down Expand Up @@ -200,3 +205,15 @@ def create(self):
size = humanfriendly.format_size(image.attrs["Size"])
elapsed = pretty_print.elapsed(self._start)
_logger.info(f"Built Docker image {self.image_name} size {size} in {elapsed}.")


import sys
from exasol.ds.sandbox.lib.logging import set_log_level
if __name__ == "__main__":
set_log_level("info")
di = DssDockerImage("exasol/ai-lab", "9.9.9", True)
if len(sys.argv) > 1:
di.container_name = sys.argv[1]
di._install_dependencies()
else:
di.create()
31 changes: 24 additions & 7 deletions exasol/ds/sandbox/runtime/ansible/ai_lab_docker_playbook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,39 @@
vars:
ansible_python_interpreter: python3
tasks:
- name: Add docker container to inventory
- name: Add Docker Container to Ansible Inventory
add_host:
name: "{{docker_container}}"
groups: docker_container_group
ansible_connection: docker

- name: Prepare Ansible Access
hosts: docker_container_group
gather_facts: true
vars:
my_ansible_user: "ansible"
jupyter_user: "jupyter"
jupyter_group: "jupyter"
jupyter_user_home: "/home/jupyter"
need_sudo: yes
tasks:
- import_tasks: apt_update.yml
- name: Ansible Access
include_role:
name: ansible_access

- name: Setup AI-Lab Docker Container
hosts: docker_container_group
remote_user: "ansible"
gather_facts: true
vars:
ansible_python_interpreter: python3
user_name: "{{ ansible_user_id }}"
user_home: "{{ ansible_env.HOME }}"
initial_notebook_folder: "{{ user_home }}/notebook-defaults"
need_sudo: false
docker_integration_test: true
ansible_python_interpreter: python3
user_name: "jupyter"
user_group: "jupyter"
user_home: "/home/jupyter"
initial_notebook_folder: "{{ user_home }}/notebook-defaults"
need_sudo: yes
docker_integration_test: true
tasks:
- import_tasks: general_setup_tasks.yml
- import_tasks: cleanup_tasks.yml
4 changes: 4 additions & 0 deletions exasol/ds/sandbox/runtime/ansible/apt_update.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- name: Update and upgrade apt packages
apt:
upgrade: yes
update_cache: yes
4 changes: 4 additions & 0 deletions exasol/ds/sandbox/runtime/ansible/create_jupyter_user.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- name: Add user 'jupyter' for running jupyter
ansible.builtin.user:
name: "{{ user_name }}"
home: "{{ user_home }}"
1 change: 1 addition & 0 deletions exasol/ds/sandbox/runtime/ansible/ec2_playbook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
need_sudo: yes
remote_user: ubuntu
tasks:
- import_tasks: apt_update.yml
- import_tasks: general_setup_tasks.yml
- import_tasks: ec2_setup_tasks.yml
- import_tasks: cleanup_tasks.yml
17 changes: 12 additions & 5 deletions exasol/ds/sandbox/runtime/ansible/general_setup_tasks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,12 @@
initial: "{{ initial_notebook_folder }}"
final: "{{user_home}}/notebooks"
cacheable: yes
- name: Update and upgrade apt packages
apt:
upgrade: yes
update_cache: yes
become: "{{need_sudo}}"
- name: Install rsync
include_role:
name: rsync
- name: Create Group and User for Running Jupyter Server
include_role:
name: jupyter_user
- name: Copy Entry Point Script
include_role:
name: entrypoint
Expand All @@ -36,7 +34,16 @@
jupyterlab_password: "{{ dss_facts.jupyter.password }}"
jupyterlab_notebook_folder_initial: "{{ dss_facts.notebook_folder.initial }}"
jupyterlab_notebook_folder: "{{ dss_facts.notebook_folder.final }}"
- name: Change owner of all files and dirs in home directory
ansible.builtin.file:
path: "{{ user_home }}"
owner: "{{ user_name }}"
group: "{{ user_group }}"
recurse: true
become: "{{ need_sudo }}"
- name: Clear pip cache
# TBD: do we need become: "{{ need_sudo }}" here?
# should folder /root be replaced by {{ user_home }} ?
ckunki marked this conversation as resolved.
Show resolved Hide resolved
ansible.builtin.file:
path: /root/.cache/pip
state: absent
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---

apt_dependencies:
- sudo=1.8.31-1ubuntu1.5
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
- name: Install sudo
apt:
name: "{{apt_dependencies}}"
state: latest
install_recommends: false

- name: Add dedicated user for executing ansible tasks
ansible.builtin.user:
name: "{{ my_ansible_user }}"
- name: Add to sudoers
community.general.sudoers:
name: Add user ansible
user: "{{ my_ansible_user }}"
state: present
nopassword: true
commands: ALL
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
regexp: ^[^#].*core
line: '* hard core 0'
create: true
become: "{{ need_sudo }}"
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@

apt_dependencies:
- apt-transport-https=2.0.10
- gpg-agent=2.2.19-3ubuntu2.2
- ca-certificates=20230311ubuntu0.20.04.1
- software-properties-common=0.99.9.12
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
name: "{{apt_dependencies}}"
state: latest
update_cache: true
install_recommends: false
become: "{{need_sudo}}"

- name: Add Docker GPG apt Key
Expand All @@ -22,11 +23,12 @@
name: docker-ce
state: latest
update_cache: true
install_recommends: false
become: "{{need_sudo}}"

- name: Adding docker users (for use without sudo)
user:
name: "{{user_name}}"
append: yes
groups: docker
become: "{{need_sudo}}"
become: "{{need_sudo}}"
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@
src: "entrypoint.py"
dest: "{{ dss_facts.entrypoint }}"
mode: 0644
group: "{{ user_group }}"
owner: "{{ user_name }}"
become: "{{need_sudo}}"
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
---

jupyterlab_ip: '*'
# Setting environment variable $HOME to {{user_home}} forces the directory for
# creating the config file. Unfortunately this does not affect the json file.
jupyterlab_config: "{{user_home}}/.jupyter/jupyter_lab_config.py"
# jupyterlab_config_json: "{{ansible_env.HOME}}/.jupyter/jupyter_server_config.json"
jupyterlab_config_json: "{{user_home}}/.jupyter/jupyter_server_config.json"
jupyterlab_default_url: "/lab/tree/start.ipynb"

# overridden in include_role
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ numpy==1.23.1
pandas==1.4.3
scikit-learn==1.0.2
matplotlib==3.7.4
jupysql==0.10.7
jupysql==0.10.10
sqlalchemy_exasol==4.6.3
stopwatch.py==2.0.1
boto3==1.26.163
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,20 @@
ansible.builtin.file:
path: "{{ jupyterlab_config }}"
state: absent
become: "{{ need_sudo }}"

# this generates /root/.jupyter/jupyter_lab_config.py (it has all rows commented out)
# this config file is very large (>30K)
# it generates file ~/.jupyter/jupyter_lab_config.py
# - the config file is very large (>30K)
# - it has all rows commented out
#
# Set environment variable $HOME to {{user_home}} to force the directory for
# creating the config file. Unfortunately this does not affect the file
# jupyter_server_config.json.
- name: Generate JupyterLab config
ansible.builtin.command: "{{jupyterlab_virtualenv}}/bin/jupyter lab --generate-config"
# this command automatically outputs to ~/.jupyter/
environment:
HOME: "{{ user_home }}"
become: "{{ need_sudo }}"

- name: Edit JupyterLab config with our settings
ansible.builtin.lineinfile:
Expand All @@ -26,16 +34,21 @@
line: "c.LabApp.default_url = '{{ jupyterlab_default_url }}'"
- regexp: "c.ServerApp.port"
line: "c.ServerApp.port = {{ jupyterlab_port }}"
become: "{{ need_sudo }}"

- name: Generate a new password
expect:
command: "{{jupyterlab_virtualenv}}/bin/jupyter server password"
responses:
Enter password: "{{jupyterlab_password}}"
Verify password: "{{jupyterlab_password}}"
environment:
HOME: "{{ user_home }}"
become: "{{ need_sudo }}"

- name: Create the notebook directory
ansible.builtin.file:
path: "{{ dss_facts.notebook_folder.initial }}"
state: directory
mode: '0755'
become: "{{ need_sudo }}"
21 changes: 15 additions & 6 deletions exasol/ds/sandbox/runtime/ansible/roles/jupyter/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,42 @@
apt:
name: "{{apt_dependencies}}"
state: present
install_recommends: false
become: "{{need_sudo}}"

- name: Update pip version
include_tasks:
file: update-pip.yml

- name: Install JupyterLab and its dependencies
- name: Install JupyterLab and required packages
include_tasks:
file: install-pip-packages.yml
file: pip-install.yml
vars:
- pip_requirements_file: "requirements_jupyter.txt"
requirements_file: "jupyter_requirements.txt"

- name: Setup Jupyterlab
ansible.builtin.import_tasks: jupyterlab.yml

- name: Install dependencies used in Jupyterlab
- name: Install packages to be used inside Jupyter notebooks
include_tasks:
file: install-pip-packages.yml
file: pip-install.yml
vars:
- pip_requirements_file: "requirements_dependencies.txt"
requirements_file: "notebook_requirements.txt"

- name: Setup Systemd service
ansible.builtin.import_tasks: systemd.yml

- name: Copy tutorial notebook
ansible.builtin.import_tasks: tutorial.yml

- name: Change owner of all files and dirs in home directory
ansible.builtin.file:
path: "{{ user_home }}"
owner: "{{ user_name }}"
group: "{{ user_group }}"
recurse: true
become: "{{ need_sudo }}"

- name: Setup motd
ansible.builtin.import_tasks: motd.yml

Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
---

- name: read current server config file
shell: "cat {{user_home}}/.jupyter/jupyter_server_config.json"
shell: "cat {{jupyterlab_config_json}}"
register: jupyter_server_config
become: "{{ need_sudo }}"

- name: save the Json data to a Variable as a Fact
set_fact:
Expand All @@ -25,5 +26,4 @@
with_items:
- 'etc/update-motd.d/999-jupyter'
vars:
jupyter_server_config_file: "{{user_home}}/.jupyter/jupyter_server_config.json"
heading_jupyter_update_password: "{{lookup('ansible.builtin.file', 'heading_jupyter_update_password.txt') }}"
ckunki marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---

- name: Copy requirements file {{ requirements_file }}
ansible.builtin.copy:
src: "{{requirements_file}}"
dest: "/tmp/{{requirements_file}}"
mode: 0644
register: copy_req_file

- name: Call pip install {{ requirements_file }}
ansible.builtin.pip:
requirements: "{{ copy_req_file.dest }}"
state: latest
virtualenv: "{{jupyterlab_virtualenv}}"
virtualenv_python: python3.8
become: "{{need_sudo}}"

- name: Remove requirements file {{ requirements_file }}
ansible.builtin.file:
path: "{{ copy_req_file.dest }}"
state: absent
15 changes: 15 additions & 0 deletions exasol/ds/sandbox/runtime/ansible/roles/jupyter/tasks/tutorial.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,18 @@
ansible.builtin.synchronize:
src: "notebook/"
dest: "{{ jupyterlab_notebook_folder_initial }}"
become: "{{ need_sudo }}"

# 1. create_image.py adds this directory as volume mount point to the Docker
# image which makes root the owner. 2. entrypoint.py running as separate user
# fails to copy the notebook files to it. 3. Mitigation: Ansible creates the
# directory in advance with appropriate owner.

- name: Create directory for final notebooks
ansible.builtin.file:
path: "{{ jupyterlab_notebook_folder }}"
state: directory
owner: "{{ user_name }}"
group: "{{ user_group }}"
mode: '0755'
become: "{{ need_sudo }}"
Loading
Loading