> ## Documentation Index
> Fetch the complete documentation index at: https://docs.domino.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Manually create an Environment with a pre-built image

<Warning>
  This is an advanced topic to assist with customizing images for use in Domino without using the automatic compatibility feature.
</Warning>

When you create an Environment with the automatic compatibility feature selected, Domino adds several Dockerfile commands so that the custom images can launch Job and Workspace containers.

At a high level, these instructions perform the following actions:

* Create a non-root Domino user.

* Install `sudo` and `curl`.

  For these images to work in Domino, you must have `Sudo` and `curl` installations. `curl` transfers data. Use `sudo` to install additional packages and libraries in the container, depending on the permissions set up by your Domino administrator.

* Add an isolated directory, `/opt/domino/`, with the tools required to run Domino Workspaces.

If you have enabled non-root executions, refer to [Create the image compatible with non-root executions](#create-the-image-compatible-with-non-root-executions).

## Create the image

1. Use the following Dockerfile instructions to replicate these steps when building a custom image.

   ```dockerfile theme={null}
   # Ensure you are injecting as the root user
   USER root

   # Add a Domino user and group ID
   ARG DOMINO_USER='domino'
   ARG DOMINO_GROUP='domino'

   # The variable names that can be used in generation of Environment scripts
   ARG ALLENV="$INSTALL_DIR,$INSTALL_BIN,$CONDA_DIR,$DOMINO_UID,$DOMINO_GID,$DOMINO_USER,$DOMINO_GROUP,$VSCODE_DIR,$VSCODE_EXT_DIR"
   RUN groupadd -g 12574 ${DOMINO_GROUP} && \
     useradd -u 12574 -g 12574 -m -N -s /bin/bash ${DOMINO_USER};

   # Install common dependencies for the compiler and setting things up
   ARG INSTALL_DIR=/opt/domino
   ARG INSTALL_BIN=${INSTALL_DIR}/bin
   ARG CONDA_DIR=${INSTALL_DIR}/conda
   RUN apt-get update && \
       apt-get -y install \
       build-essential \
       gettext-base \
       gnupg && \
     apt-get clean && \
     rm -rf /var/lib/apt/lists/* && \
     mkdir -p \
         ${INSTALL_DIR} \
         ${INSTALL_BIN} \
         ${CONDA_DIR}

   # Recommended: Add domino user account to sudoers
   RUN echo "${DOMINO_USER}    ALL=NOPASSWD: ALL" >> /etc/sudoers

   # Set to a Domino supported language to prevent unrecognized character input
   RUN echo "export LANG=${LANG}" >> /home/${DOMINO_USER}/.domino-defaults && \
       echo "export LC_ALL=${LANG}" >> /home/${DOMINO_USER}/.domino-defaults && \
       echo 'export PYTHONIOENCODING=utf-8' >> /home/${DOMINO_USER}/.domino-defaults && \
       chown -R ${DOMINO_USER}.${DOMINO_GROUP} "/home/${DOMINO_USER}"

   # Load Domino defaults
   RUN if [ -f /home/${DOMINO_USER}/.domino-defaults ]; then \
           echo "source /home/${DOMINO_USER}/.domino-defaults" >> /home/${DOMINO_USER}/.bashrc; \
       fi

   # Install Sudo and Curl
   # Note that this will only work with Debian and Ubuntu
   RUN apt update && apt install -y --no-install-recommends \
           curl \
           sudo \
       apt-get clean && \
       rm -rf /var/lib/apt/lists/*
   ```

2. If you want JupyterLab or any IDE in this workspace, define a start script for each. See [Replace Default Environment Tools](/cloud/platform-capabilities/core-concepts/compute-environments/work-with-pluggable-workspaces/configure-native-workspaces) for an example. These start scripts are stored in `/opt/domino/workspaces` by default.

3. Add a new field to your Environment’s **Pluggable Workspace Tools** for the associated tool and set the **start** field to the location of your start script.

## Create the image compatible with non-root executions

Images shouldn’t add users to sudoers, according to the non-root executions principle. It is recommended to build environment images with the packages you need, rather than relying on a root user for runtime package installation, for increased reproducibility and security in your environment.

1. Use the following Dockerfile instructions to replicate these steps when building a custom image.

   ```dockerfile theme={null}
   # Add a Domino user and group ID
   ARG DOMINO_USER='domino'
   ARG DOMINO_GROUP='domino'

   # The variable names that can be used in generation of environment scripts
   ARG ALLENV="$INSTALL_DIR,$INSTALL_BIN,$CONDA_DIR,$DOMINO_UID,$DOMINO_GID,$DOMINO_USER,$DOMINO_GROUP,$VSCODE_DIR,$VSCODE_EXT_DIR"
   RUN groupadd -g 12574 ${DOMINO_GROUP} && \
     useradd -u 12574 -g 12574 -m -N -s /bin/bash ${DOMINO_USER};

   # Install common dependencies for the compiler and setting things up
   ARG INSTALL_DIR=/opt/domino
   ARG INSTALL_BIN=${INSTALL_DIR}/bin
   ARG CONDA_DIR=${INSTALL_DIR}/conda
   RUN apt-get update && \
       apt-get -y install \
       build-essential \
       gettext-base \
       gnupg && \
     apt-get clean && \
     rm -rf /var/lib/apt/lists/* && \
     mkdir -p \
         ${INSTALL_DIR} \
         ${INSTALL_BIN} \
         ${CONDA_DIR}

   # Set to a Domino supported language to prevent unrecognized character input
   RUN echo "export LANG=${LANG}" >> /home/${DOMINO_USER}/.domino-defaults && \
       echo "export LC_ALL=${LANG}" >> /home/${DOMINO_USER}/.domino-defaults && \
       echo 'export PYTHONIOENCODING=utf-8' >> /home/${DOMINO_USER}/.domino-defaults && \
       chown -R ${DOMINO_USER}.${DOMINO_GROUP} "/home/${DOMINO_USER}"

   # Load Domino defaults
   RUN if [ -f /home/${DOMINO_USER}/.domino-defaults ]; then \
           echo "source /home/${DOMINO_USER}/.domino-defaults" >> /home/${DOMINO_USER}/.bashrc; \
       fi

   # Install Curl
   # Note that this will only work with Debian and Ubuntu
   RUN apt update && apt install -y --no-install-recommends \
           curl \
       apt-get clean && \
       rm -rf /var/lib/apt/lists/*
   ```

2. If you want JupyterLab or any IDE in this workspace, define a start script for each. See [Replace Default Environment Tools](/cloud/platform-capabilities/core-concepts/compute-environments/work-with-pluggable-workspaces/configure-native-workspaces) for an example. These start scripts are stored in `/opt/domino/workspaces` by default.

3. Add a new field to your environment’s **Pluggable Workspace Tools** for the associated tool and set the **start** field to the location of your start script.

## Optional: Enable JupyterLab

If you want to use JupyterLab in a Domino workspace that uses a custom image, use the following instructions to install with `miniconda`. The commands to install Tensorboard are included, and the comments indicate which lines to remove if you do not need Tensorboard in your image.

```dockerfile theme={null}
# Install JupyterLab and Tensorboard using Conda
# A proper combination of these versions is important!
ARG CONDA_URL=https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh
ARG PYTHON_VERSION=3.9
ARG JUPYTER_VERSION=2.3

# Remove the following line if you are not installing Tensorboard:
ARG TENSORBOARD_VERSION=2.2

# You must create a start script with configurations for JupyterLab
ARG JUPYTER_SCRIPT=jupyterlab-start.sh

# Install Conda and Python
# (Download signature not available)
RUN curl -o conda-install.sh -LSsf ${CONDA_URL} && \
  /bin/bash conda-install.sh -fbp ${CONDA_DIR} && \
  ${CONDA_DIR}/bin/conda update -y --update-all && \
  ${CONDA_DIR}/bin/conda install -y python=${PYTHON_VERSION}

# Install NodeJS if installing Tensorboard
RUN ${CONDA_DIR}/bin/conda install -y nodejs && \
  mkdir -p ${INSTALL_DIR}/node && \
  ln -rs ${CONDA_DIR}/bin/node ${INSTALL_DIR}/node/ && \
  ln -rs ${CONDA_DIR}/bin/npm ${INSTALL_DIR}/node/

# Install and configure Jupyterlab and extensions
RUN ${CONDA_DIR}/bin/conda install -y jupyterlab=${JUPYTER_VERSION} && \
  ${CONDA_DIR}/bin/conda install -y tensorboard=${TENSORBOARD_VERSION} && \
  ${CONDA_DIR}/bin/conda install -y -c conda-forge jupytext && \
  ${CONDA_DIR}/bin/conda install -y nodejs && \
  ${CONDA_DIR}/bin/pip install jupyter_tensorboard && \
  PATH=${CONDA_DIR}/bin ${CONDA_DIR}/bin/jupyter labextension install jupyterlab_tensorboard

# Create Juptyerlab workspace Environment scripts
RUN envsubst "${ALLENV}" < ${JUPYTER_SCRIPT} > ${INSTALL_BIN}/${JUPYTER_SCRIPT} && \
  chmod 755 ${INSTALL_BIN}/${JUPYTER_SCRIPT}
```

## Optional: Enable VS Code

To use VS Code in a Domino workspace, add the following instructions.

```dockerfile theme={null}
# Install VS Code

#Set Versions
ARG VSCODE_VERSION=3.10.2
ARG VSCODE_URL=https://github.com/cdr/code-server/releases/download/v${VSCODE_VERSION}/code-server-${VSCODE_VERSION}-linux-amd64.tar.gz
ARG VSCODE_PYTHON_VERSION=2021.5.926500501
ARG VSCODE_PYTHON_URL=https://github.com/microsoft/vscode-python/releases/download/${VSCODE_PYTHON_VERSION}/ms-python-release.vsix

# Where it will be deployed
ARG VSCODE_DIR=${INSTALL_DIR}/vscode
ARG VSCODE_EXT_DIR=${VSCODE_DIR}/extensions

# You must create a start script with configurations for VS Code
ARG VSCODE_SCRIPT=vscode-start.sh
RUN curl -LSsf ${VSCODE_URL} | tar -xz --no-same-permissions && \
  mv -f code-server-${VSCODE_VERSION}-linux-amd64 ${VSCODE_DIR} && \
  curl -o python.vsix -LSsf ${VSCODE_PYTHON_URL} && \
  mkdir -p ${VSCODE_EXT_DIR} && \
  ${VSCODE_DIR}/bin/code-server \
      --install-extension python.vsix \
      --extensions-dir ${VSCODE_EXT_DIR}

# Create VS Code workspace Environment scripts
RUN envsubst "${ALLENV}" < ${VSCODE_SCRIPT} > ${INSTALL_BIN}/${VSCODE_SCRIPT} && \
  chmod 755 ${INSTALL_BIN}/${VSCODE_SCRIPT}
```
