Search code examples
dockermicromamba

Micromamba inside Docker container


I have a base Docker image:

FROM ubuntu:21.04

WORKDIR /app

RUN apt-get update && apt-get install -y wget bzip2 \
    && wget -qO-  https://micromamba.snakepit.net/api/micromamba/linux-64/latest | tar -xvj bin/micromamba \
    && touch /root/.bashrc \
    && ./bin/micromamba shell init -s bash -p /opt/conda  \
    && cp /root/.bashrc /opt/conda/bashrc \
    && apt-get clean autoremove --yes \
    && rm -rf /var/lib/{apt,dpkg,cache,log}

SHELL ["bash", "-l" ,"-c"]

and derive from it another one:

ARG BASE
FROM $BASE

RUN source /opt/conda/bashrc && micromamba activate \
    && micromamba create --file environment.yaml -p /env

While building the second image I get the following error: micromamba: command not found for the RUN section.

  1. If I run 1st base image manually I can launch micromamba, it is running correctly
  2. I can run temporary image which were created for 2nd image building, micromamba is available via CLI, running correctly.
  3. If I inherit from debian:buster, or alpine, for example, it is building perfectly.

What a problem with the Ubuntu? Why it cannot see micromamba during 2nd Docker image building?

PS using scaffold for building, so it can understand correctly, where is $BASE and what is it.


Solution

  • The ubuntu:21.04 image comes with a /root/.bashrc file that begins with:

    # ~/.bashrc: executed by bash(1) for non-login shells.
    # see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
    # for examples
    
    # If not running interactively, don't do anything
    [ -z "$PS1" ] && return
    

    When the second Dockerfile executes RUN source /opt/conda/bashrc, PS1 is not set and thus the remainder of the bashrc file does not execute. The remainder of the bashrc file is where micromamba initialization occurs, including the setup of the micromamba bash function that is used to activate a micromamba environment.

    The debian:buster image has a smaller /root/.bashrc that does not have a line similar to [ -z "$PS1" ] && return and therefore the micromamba function gets loaded.

    The alpine image does not come with a /root/.bashrc so it also does not contain the code to exit the file early.

    If you want to use the ubuntu:21.04 image, you could modify you first Dockerfile like this:

    FROM ubuntu:21.04
    
    WORKDIR /app
    
    RUN apt-get update && apt-get install -y wget bzip2 \
        && wget -qO-  https://micromamba.snakepit.net/api/micromamba/linux-64/latest | tar -xvj bin/micromamba \
        && touch /root/.bashrc \
        && ./bin/micromamba shell init -s bash -p /opt/conda  \
        && grep -v '[ -z "\$PS1" ] && return' /root/.bashrc  > /opt/conda/bashrc   # this line has been modified \
        && apt-get clean autoremove --yes \
        && rm -rf /var/lib/{apt,dpkg,cache,log}
    
    SHELL ["bash", "-l" ,"-c"]
    

    This will strip out the one line that causes the early termination.

    Alternatively, you could make use of the existing mambaorg/micromamba docker image. The mambaorg/micromamba:latest is based on debian:slim, but mambaorg/micromamba:jammy will get you a ubuntu-based image (disclosure: I maintain this image).