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

Dockerfile #9

Closed
hajsf opened this issue Dec 21, 2023 · 4 comments
Closed

Dockerfile #9

hajsf opened this issue Dec 21, 2023 · 4 comments

Comments

@hajsf
Copy link

hajsf commented Dec 21, 2023

I'm trying to build a docker file for mojo lang, it was done smoothly using Ubuntu vase image as:

FROM ubuntu:latest

ARG DEFAULT_TZ=Asia/Gaza
# A random default token
ARG AUTH_KEY=mut_a2fxxxxxxxxxxxxxx18f
ARG MODULAR_HOME="/root/.modular"

ENV MODULAR_HOME=$MODULAR_HOME
ENV PATH="$PATH:$MODULAR_HOME/pkg/packages.modular.com_mojo/bin"

RUN apt-get update \
   && DEBIAN_FRONTEND=noninteractive TZ=$DEFAULT_TZ apt-get install -y \
    tzdata \
    curl \
    git \
    wget && \
    rm -rf /var/lib/apt/lists/*

# Download the latest version of minicoda py3.8 for linux x86/x64.
RUN curl -fsSL https://repo.anaconda.com/miniconda/$( wget -O - https://repo.anaconda.com/miniconda/ 2>/dev/null | grep -o 'Miniconda3-py38_[^"]*-Linux-x86_64.sh' | head -n 1) > /tmp/miniconda.sh \
       && chmod +x /tmp/miniconda.sh \
       && /tmp/miniconda.sh -b -p /opt/conda

ENV PATH=/opt/conda/bin:$PATH

RUN conda init

RUN curl https://get.modular.com | sh - && \
    modular auth $AUTH_KEY 

RUN pip install --upgrade pip
RUN modular clean
RUN modular install mojo

EXPOSE 3000

# Change permissions to allow for Apptainer/Singularity containers
RUN chmod -R a+rwX /root

ENTRYPOINT ["tail"]
CMD ["-f","/dev/null"]

And I tried to do the same based on archlinux base image, but I struggled in that, I updated the install.py file to be:

import os
import shutil
import subprocess
import sys
import urllib.request

# TODO use shutil to copy files

arch = "x86_64-linux-gnu"


def param(name: str):
    try:
        return os.environ[name]
    except:
        return None


home = param("HOME")
if home is None:
    home = "~"

WORKING_DIR = "~/.local/arch-mojo/"

mojo_lib_path_from_home = ".local/lib/mojo"
mojo_lib_path = f"{home}/{mojo_lib_path_from_home}"
token = "mut_a2xxxxxxxxxxxxxxxxxxxxxxx18f"

modular = shutil.which("modular") is not None

authenticated = False
if modular:
    authenticated = "user.id" in subprocess.run(["modular", "config-list"], capture_output=True).stdout.decode("utf-8")

WORKING_DIR = WORKING_DIR.replace("~", param("HOME"))
if WORKING_DIR[-1] != "/":
    WORKING_DIR += "/"

try:
    os.makedirs(WORKING_DIR)
except FileExistsError:
    pass
 
# install modular if not installed
if not modular:
    # download PKGBUILD
    urllib.request.urlretrieve("https://raw.githubusercontent.com/Sharktheone/arch-mojo/main/PKGBUILD",
                               f"{WORKING_DIR}PKGBUILD")
    os.system(f"cd {WORKING_DIR} && makepkg -si")

# authenticate in modular
if not authenticated:
    os.system(f"LD_LIBRARY_PATH=$LD_LIBRARY_PATH:{mojo_lib_path} modular auth {token}")

# download ncurses lib

urllib.request.urlretrieve("https://ftp.debian.org/debian/pool/main/n/ncurses/libncurses6_6.4-4_amd64.deb",
                           f"{WORKING_DIR}libncurses.deb")

urllib.request.urlretrieve("https://ftp.debian.org/debian/pool/main/libe/libedit/libedit2_3.1-20221030-2_amd64.deb",
                           f"{WORKING_DIR}libedit.deb")

os.system(f"cd {WORKING_DIR} && ar -vx libncurses.deb && tar -xf data.tar.xz")
os.system(f"cd {WORKING_DIR} && ar -vx libedit.deb && tar -xf data.tar.xz")


# copy libs
os.system(f"sudo cp {WORKING_DIR}lib/{arch}/libncurses.so.6.4 /lib/libncurses.so.6.4")
os.system(f"sudo cp {WORKING_DIR}usr/lib/{arch}/libform.so.6.4 /usr/lib/libform.so.6.4")
os.system(f"sudo cp {WORKING_DIR}usr/lib/{arch}/libpanel.so.6.4 /usr/lib/libpanel.so.6.4")
os.system(f"sudo cp {WORKING_DIR}usr/lib/{arch}/libedit.so.2.0.70 /usr/lib/libedit.so.2.0.70")

os.system("sudo ln -s /lib/libncurses.so.6.4 /lib/libncurses.so.6")
os.system("sudo ln -s /usr/lib/libform.so.6.4 /usr/lib/libform.so.6")
os.system("sudo ln -s /usr/lib/libpanel.so.6.4 /usr/lib/libpanel.so.6")
os.system("sudo ln -s /usr/lib/libedit.so.2.0.70 /usr/lib/libedit.so.2")

# install mojo
mojo = shutil.which(f"PATH=$PATH:{home}/.modular/pkg/packages.modular.com_mojo/bin/ mojo") is not None
if mojo:
    print("Mojo is already installed... cleaning up")
    os.system(f"PATH=$PATH:{home}/.modular/pkg/packages.modular.com_mojo/bin/ modular clean")

os.system(f"LD_LIBRARY_PATH=$LD_LIBRARY_PATH:{mojo_lib_path} modular install mojo")

# fix crashdb directory not found:
os.makedirs(f"{home}/.modular/crashdb", exist_ok=True)


def rc_path():
    return f"{param('HOME')}/.bashrc"

rc_pth = rc_path()

if rc_pth is None:
    print("Skipping rc file installation")
    exit(0)

rc_file = open(rc_pth, "a")
shell_rc = open(rc_pth, "r").read()

# check if exports are already in rc file
if param("LD_LIBRARY_PATH") is None or \
        f"~/{mojo_lib_path_from_home}" not in param("LD_LIBRARY_PATH") \
        or mojo_lib_path not in param("LD_LIBRARY_PATH"):
    rc_file.write(f"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/{mojo_lib_path_from_home}\n")

if param("PATH") is None \
        or "~/.modular/pkg/packages.modular.com_mojo/bin/" not in param("PATH") \
        or f"{home}.modular/pkg/packages.modular.com_mojo/bin/" not in param("PATH"):
    rc_file.write("export PATH=$PATH:~/.modular/pkg/packages.modular.com_mojo/bin/\n")
rc_file.close()

And wrote the Dockerfile as:

# Use an existing docker image as a base
FROM archlinux/archlinux:base

# Set timezone
ARG DEFAULT_TZ=Asia/Gaza
ENV TZ=$DEFAULT_TZ

# Update Archlinux core and extra / Install necessary tools
RUN pacman -Syu --noconfirm curl

# Install tzdata and set timezone
RUN pacman -Syu --noconfirm tzdata && \
    ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone && \
    pacman -Scc --noconfirm

# Install necessary tools
RUN pacman -Syu --noconfirm curl wget grep python

# Download the latest version of minicoda py3.8 for linux x86/x64.
RUN curl -fsSL https://repo.anaconda.com/miniconda/$( wget -O - https://repo.anaconda.com/miniconda/ 2>/dev/null | grep -o 'Miniconda3-py38_[^"]*-Linux-x86_64.sh' | head -n 1) > /tmp/miniconda.sh \
       && chmod +x /tmp/miniconda.sh \
       && /tmp/miniconda.sh -b -p /opt/conda

ENV PATH=/opt/conda/bin:$PATH

RUN conda init

RUN conda create -n venv python=3.10

# Upgrade pip and install necessary Python packages
RUN python -m ensurepip --upgrade && \
    pip install --upgrade pip setuptools wheel

# Define an environment variable for the auth token
ENV MODULAR_TOKEN=mut_a2ff2b6187ae4aa885abe2010053518f

# Define an environment variable for MODULAR_HOME
ENV MODULAR_HOME /home/tempuser/.modular

# Install necessary tools
RUN pacman -S fakeroot binutils sudo --noconfirm
# python python-pip
# Create a new user, switch to it, and set a password
RUN useradd -m tempuser
RUN echo 'tempuser:password' | chpasswd

# Add tempuser to the wheel group
RUN usermod -aG wheel tempuser

# Grant sudo privileges to the wheel group
RUN echo '%wheel ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers

USER tempuser

# Copy the install.py file from your local machine to the Docker image
COPY install.py .

# Use the auth token in the command
# Use 'yes' to automatically answer 'Y' to any prompts
RUN yes | python install.py

#RUN python -m venv /home/tempuser/venv
#RUN source /home/tempuser/venv/bin/activate
RUN modular clean
RUN modular install mojo

EXPOSE 3000

# Change permissions to allow for Apptainer/Singularity containers
RUN chmod -R a+rwX /root

ENTRYPOINT ["tail"]
CMD ["-f","/dev/null"]

But i got the below at the last stage:

111.3 [notice] A new release of pip is available: 23.0.1 -> 23.3.2
111.3 [notice] To update, run: pip install --upgrade pip
115.3 [mojo] Testing: `mojo build test_mandelbrot.mojo` [FAIL]
115.3 [mojo] Testing: `mojo build test_python.mojo` [FAIL]
115.3 [mojo] Testing: `mojo repl` [FAIL]
115.3 [mojo] Some components may have been installed successfully, but others may not work as expected. Please submit an issue to https://github.com/modularml/mojo and include the full output of the command you just ran.
117.2 modular: error: failed to run python: 
117.2 # Found release for https://packages.modular.com/mojo @ 0.6.1
117.2 # Installing to /home/tempuser/.modular/pkg/packages.modular.com_mojo
117.2 # Downloading artifacts. Please wait...
117.2 # Downloads complete, setting configs...
117.2 # Configs complete, running post-install hooks...
------
Dockerfile.arch:65
--------------------
  63 |     #RUN source /home/tempuser/venv/bin/activate
  64 |     RUN modular clean
  65 | >>> RUN modular install mojo
  66 |     
  67 |     EXPOSE 3000
--------------------
ERROR: failed to solve: process "/bin/sh -c modular install mojo" did not complete successfully: exit code: 1

 *  The terminal process "/usr/bin/bash '-c', 'docker build --pull --rm -f "Dockerfile.arch" -t mojo-arch:latest "."'" terminated with exit code: 1. 
 *  Terminal will be reused by tasks, press any key to close it.

Can you help in this please. thanks

@Sharktheone
Copy link
Owner

Have you tried the Dockerfile from modular? I haven't tried it, but it should work on arch since it is docker

@hajsf
Copy link
Author

hajsf commented Dec 23, 2023

I have sone issues with, but I was to build my own docker using ubuntu as below:
.env file:

MODULAR_AUTH_KEY=mut_a2ffxxxxxxxxxxxxxxxxxx8f

auth_script.sh file:

#!/bin/bash

# Read the MODULAR_AUTH_KEY from the .env file and execute modular auth
export $(cat .env | xargs) && \
modular auth $MODULAR_AUTH_KEY

Dockerfile.mojosdk:

# Use the latest Ubuntu base image
FROM ubuntu:latest

# Set environment variable to avoid interactive prompts during package installation
ENV DEBIAN_FRONTEND=noninteractive

# Set working directory inside the container
WORKDIR /app

# Copy necessary files into the container
COPY auth_script.sh .
COPY .env .

# Update package lists and install required packages
RUN apt-get update &&  \
    apt-get install -y \
    software-properties-common \
    gnupg \
    git \
    curl \
    wget \
    && apt-get clean && rm -rf /var/lib/apt/lists/* \
    && set -eux; \
    # Add Python 3.10 repository and install dependencies
    add-apt-repository ppa:deadsnakes/ppa -y \
    && keyring_location=/usr/share/keyrings/modular-installer-archive-keyring.gpg \
    && curl -1sLf 'https://dl.modular.com/bBNWiLZX5igwHXeu/installer/gpg.0E4925737A3895AD.key' | gpg --dearmor >> ${keyring_location} \
    && curl -1sLf 'https://dl.modular.com/bBNWiLZX5igwHXeu/installer/config.deb.txt?distro=debian&codename=wheezy' > /etc/apt/sources.list.d/modular-installer.list \
    && apt-get update \
    && apt install -y python3.10 python3.10-venv \
    && apt-get install -y modular \
    && apt-get clean && rm -rf /var/lib/apt/lists/* \
    # Set environment variables for Mojo installation
    && echo 'export MODULAR_HOME="/root/.modular"' >> ~/.bashrc \
    && echo 'export PATH="/root/.modular/pkg/packages.modular.com_mojo/bin:$PATH"' >> ~/.bashrc \
    && /bin/bash -c "source ~/.bashrc" \
    # Clean up and set permissions
    && modular clean \
    && chmod +x auth_script.sh \
    && ./auth_script.sh \
    && modular install mojo \
    && pip install --upgrade pip

# Clean up unnecessary packages and files
RUN apt-get remove -y \
    software-properties-common \
    gnupg \
    && apt-get autoremove -y \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
    && apt-get purge -y --auto-remove

# Remove the copied script and environment file
RUN rm auth_script.sh .env

# Expose port 80 for external access
EXPOSE 80

# Set default entrypoint and command for the container
ENTRYPOINT ["tail"]
CMD ["-f", "/dev/null"]

Build the container:

docker build -t mojo-sdk:r0.6 -f Dockerfile.mojosdk --no-cache .

Create a volume for the projects:

docker volume create mojoProjects

Create and run the develi=opment container, and map it with the docker volme

docker run -d --publish 3000:80 --name mojo-dev --mount source=mojoProjects,target=/app mojo-sdk:r0.6

The generated image size is 1256 MB, and it is working very well.

I'm just excited if docker image of the same can be built using Archlinux docker image as a base. Thanks

@Sharktheone
Copy link
Owner

I guess, alpine, debian (or ubuntu) fit best for a container base image.

From what I'm reading, your issue is solved, so I can close this?

@hajsf
Copy link
Author

hajsf commented Dec 24, 2023

Thanks a lot, yes you can close it, I just created a repository of my working if any one here is interested. https://github.com/hajsf/mojo-docker/tree/main

@hajsf hajsf closed this as completed Dec 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants