Sharktheone / arch-mojo

Install Mojo on Arch
89 stars 10 forks source link

Dockerfile #9

Closed hajsf closed 9 months ago

hajsf commented 9 months ago

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 commented 9 months ago

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

hajsf commented 9 months ago

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 commented 9 months ago

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 commented 9 months ago

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