Skip to content

Instantly share code, notes, and snippets.

@NikolausDemmel
Last active February 2, 2017 19:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NikolausDemmel/9248dcde78a4d725cda8cdee32ed67fe to your computer and use it in GitHub Desktop.
Save NikolausDemmel/9248dcde78a4d725cda8cdee32ed67fe to your computer and use it in GitHub Desktop.
MARV Robotics EE docker
*
!Dockerfile
!certificates/
!marv_entrypoint.sh
!marv_env.sh
!src
src/*/.git

This is just some example of how to use MARV with docker with some specifics to our setup, so you should take what you need, and remove what you don't.

Some example usage:

Dev setup manually starting containers

Init config (you only need this if you don't have a config in ./site/ yet, or if you want to reinitialize with the latest default config):

# from git repo root
docker run \
    -v $PWD/site:/marv/site \
    -e "MARV_USERID=$(id -u)" \
    -e "MARV_GROUPID=$(id -g)" \
    -it --rm \
    --name marv \
    --user marv \
    zeno-marv-robotics \
    bash -c "marv init /marv/site"

Start container:

# from git repo root
docker run \
    -v $PWD/site:/marv/site \
    -v $PWD/../zeno-marv-nodes:/marv/src/zeno-marv-nodes \
    -v $HOME/data/marv_test/bags:/mnt/bags:ro \
    -v $HOME/data/marv_test/tests:/mnt/tests:ro \
    -e "MARV_USERID=$(id -u)" \
    -e "MARV_GROUPID=$(id -g)" \
    -p 5000 \
    -p 5001:8000 \
    --detach \
    --name marv \
    zeno-marv-robotics

You can open MARV in the browser at http://localhost:5001/.

Interactive session for executing commands:

docker exec -itu marv marv /bin/bash

[...]

marv --help

Setup with docker compose

docker-compose.yml:

version: '2.1'
services:
  marv:
    image: "si0vmc1062.de.bosch.com/zenoway/zeno-marv-robotics"
    volumes:
     - "./site-bags:/marv/site"
    environment:
     - MARV_USERID
     - MARV_GROUPID

docker-compose.override.yml:

version: '2.1'
services:
  marv:
    image: "zeno-marv-robotics"
    build: .
    volumes:
     - "${HOME}/data/marv_test/bags:/mnt/bags:ro"
     - "${HOME}/data/marv_test/tests:/mnt/tests:ro"
     - "../marv-robotics-ee:/marv/src/marv-robotics-ee"
     - "../zeno-marv-nodes:/marv/src/zeno-marv-nodes"

docker-compose.prod.yml:

version: '2.1'
services:
  marv:
    volumes:
     - "/var/lib/marv-robotics/site-bags:/marv/site"
     - "/vol/bags-local/bagbunker_bags:/mnt/bags:ro"
     - "/vol/bags-local/bagbunker_tests:/mnt/tests:ro"
    restart: unless-stopped
FROM ros:indigo
MAINTAINER Nikolaus Demmel <Nikolaus.Demmel@de.bosch.com>
################################################################################
## ARGUMENTS
# optional use --build-arg or ARG for proxy variables instead, but for our case
# we want them set also in the running container for convenience
ARG DOCKER_HOST_IP=172.17.0.1
ENV no_proxy="127.0.0.1,$DOCKER_HOST_IP"
ENV http_proxy=http://$DOCKER_HOST_IP:3128/
ENV https_proxy=https://$DOCKER_HOST_IP:3128/
# allow to change the uid/gid when starting the container
ENV MARV_USERID=1000
ENV MARV_GROUPID=1000
# the user and group name is not supposed to be changed when running a container,
# but it is still used in the entrypoint script
ENV MARV_USER=marv
ENV MARV_GROUP=marv
################################################################################
## BOILERPLATE
# Use the "noninteractive" debconf frontend since we're installing in a non-interactive way.
ARG DEBIAN_FRONTEND=noninteractive
# install bosch proxy certificates (for installingg gosu with https download)
RUN mkdir -p /usr/share/ca-certificates/bosch
COPY certificates/BoschInternetProxyCA2.crt /usr/share/ca-certificates/bosch
RUN for f in /usr/share/ca-certificates/bosch/*.crt; do echo "bosch/$(basename $f)" >> /etc/ca-certificates.conf; done
RUN update-ca-certificates
# gosu for easy step-down from root, which we use in our entrypoint script
# see: https://github.com/tianon/gosu
ARG GOSU_VERSION=1.9
RUN set -x \
&& apt-get update && apt-get install -y --no-install-recommends wget && rm -rf /var/lib/apt/lists/* \
&& dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')" \
&& wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch" \
&& wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc" \
&& export GNUPGHOME="$(mktemp -d)" \
&& gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \
&& gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \
&& rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc \
&& chmod +x /usr/local/bin/gosu \
&& gosu nobody true \
&& apt-get purge -y --auto-remove wget
################################################################################
## INSTALL MARV-ROBOTICS SYSTEM DEPENDENCIES
# get a more recent version of python 2.7 from a PPA
RUN apt-get update && apt-get install -y software-properties-common \
&& add-apt-repository ppa:fkrull/deadsnakes-python2.7 \
&& apt-get update \
&& apt-get upgrade -y \
&& rm -rf /var/lib/apt/lists/*
# system dependencies
RUN apt-get update && apt-get install -y \
curl \
libffi-dev \
libjpeg-dev \
libz-dev \
python2.7-dev \
python-opencv \
python-virtualenv \
ros-indigo-ros-base \
ros-indigo-cv-bridge \
ros-indigo-tf \
ros-indigo-tf-conversions \
&& rm -rf /var/lib/apt/lists/*
# get a more recent version of ffmpeg
RUN apt-get update \
&& add-apt-repository ppa:mc3man/trusty-media \
&& apt-get update \
&& apt-get install -y ffmpeg \
&& rm -rf /var/lib/apt/lists/*
################################################################################
## PREPARE USER DIR AND ENTRYPOINT
# add user and group
RUN groupadd -g $MARV_GROUPID $MARV_GROUP && \
useradd -m -u $MARV_USERID -g $MARV_GROUPID $MARV_USER
# prepare environment
RUN echo ". /marv_env.sh" >> /etc/bash.bashrc
# prepare user and directory
RUN mkdir -p /marv/site
RUN chown -R $MARV_USER:$MARV_GROUP /marv
USER $MARV_USER
WORKDIR /marv
RUN touch .firstrun
################################################################################
## INSTALL MARV ROBOTICS PYTHON DEPENDENCIES
# prepare virtualenv with ROS
RUN rosdep update
RUN . /opt/ros/indigo/setup.sh \
&& virtualenv -p python2.7 --system-site-packages venv
# upgrade/install setuptools and pip
RUN . venv/bin/activate \
&& pip install -U pip setuptools pip-tools
# install everything from reqs.txt (first only copying reqs.txt is better for docker build caching)
COPY src/marv-robotics-ee/reqs.txt src/marv-robotics-ee/reqs.txt
RUN . venv/bin/activate \
&& pip-sync src/marv-robotics-ee/reqs.txt
################################################################################
## INSTALL PYTHON PACKAGES FROM SUBMODULES
# assume that other repos like MARV itself or custom python packages with nodes are found as git submodules in the src directory
COPY src src
USER root
RUN chown -R $MARV_USER:$MARV_GROUP src
USER $MARV_USER
# Install packages in order
RUN . /marv/venv/bin/activate \
&& for p in marv-robotics-ee/marv-cli \
marv-robotics-ee/marv-rosplay \
marv-robotics-ee/marv \
marv-robotics-ee/marv-robotics \
zeno-marv-nodes; do pip install -e src/$p; done
# Install all packages (commented out; for now we list them explicitely and in order)
#RUN . /marv/venv/bin/activate \
# && find -name setup.py -not -ipath "*/marv-robotics*" -printf "%h\n" | xargs -n1 -r pip install -e
################################################################################
## DEFAULT COMMAND AND ENTRYPOINT
# default command: wsgi server; run as root since entrypoint drops privileges after setting permissions
WORKDIR /marv/site
USER root
COPY marv_entrypoint.sh /
COPY marv_env.sh /
ENTRYPOINT ["/marv_entrypoint.sh"]
CMD ["uwsgi", "--ini", "uwsgi.conf"]
#!/bin/bash
set -e
function pip_install_if_mounted()
{
DIR=$1
# we say the directory is mounted if the mount point is different from '/'
if [[ `df -P -T $DIR | tail -n +2 | awk '{print $7}'` != / ]]; then
gosu $MARV_USER pip install -e $DIR
fi
}
# setup environment
source /marv_env.sh
# cleanup the socket file (sometimes stays leftover from previous runs if the marv was to shut down cleanly)
if [[ "$1" = 'uwsgi' ]]; then
rm -f /marv/site/notify
fi
# Drop root privileges if we are running uwsgi or marv, but otherwise
# if the the container is run with `--user` or with a custom command, don't
# touch the uid
if [[ ("$1" = 'uwsgi' || "$1" = 'marv') && "$(id -u)" = '0' ]]; then
# allow the user to specify the uid/gid of the marv user
if [ -f /marv/.firstrun ]; then
# update ids of user and group
if [[ -n "$MARV_USERID" ]]; then
usermod -u $MARV_USERID $MARV_USER
fi
if [[ -n "$MARV_GROUPID" ]]; then
groupmod -g $MARV_GROUPID $MARV_GROUP
usermod -g $MARV_GROUPID $MARV_USER
fi
# Update ownership of /marv to that of the container
chown -R $MARV_USER:$MARV_GROUP /marv || true
if [ -d /marv/$MARV_USER ]; then
chown -R $MARV_USER:$MARV_GROUP /home/$MARV_USER || true
fi
# remove flag to run this only once
rm /marv/.firstrun
# pip install the marv-robotics packages in order if they are mounted
for p in marv-robotics-ee/marv-cli \
marv-robotics-ee/marv-rosplay \
marv-robotics-ee/marv \
marv-robotics-ee/marv-robotics
do
pip_install_if_mounted /marv/src/$p
done
# install other packages if they are mounted
for p in `find /marv/src -name setup.py -not -ipath "*/marv-robotics*" -printf "%h\n"`; do
pip_install_if_mounted $p
done
fi
# change arguments to run with 'gosu' (drop root privileges)
set -- gosu $MARV_USER "$@"
fi
# execute command
exec "$@"
set -e
source "/opt/ros/$ROS_DISTRO/setup.bash"
source /marv/venv/bin/activate
set +e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment