Skip to content

Commit

Permalink
[coreio/base] update docker container for two-stage system, one for s…
Browse files Browse the repository at this point in the history
…pot user to run system service and another one is for development users
  • Loading branch information
k-okada committed Nov 15, 2024
1 parent ed8a7bc commit 2e17982
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 37 deletions.
70 changes: 54 additions & 16 deletions jsk_spot_robot/coreio/base/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,33 @@ RUN apt-get update && apt install -y -q python3-catkin-pkg-modules python3-rospk
# network tools
RUN apt-get update && apt install -y -q net-tools iputils-ping dnsutils traceroute curl

# development tools
RUN apt-get update && apt install -y -q python-catkin-tools ros-melodic-catkin-virtualenv

# editors
RUN apt-get update && apt install -y -q less emacs vim

# bluetooth
RUN apt-get update && apt install -y -q bluez bluez-tools

# ROS packages
RUN apt-get update && apt install -y -q ros-melodic-catkin ros-melodic-vision-msgs

# setup user space
RUN sed -i 's@%sudo\s*ALL=(ALL:ALL)\s*ALL@%sudo ALL=(ALL:ALL) NOPASSWD: ALL@' /etc/sudoers
RUN sed -i 's@%sudo\s*ALL=(ALL:ALL)\s*ALL@%sudo ALL=(ALL) NOPASSWD: ALL@' /etc/sudoers
RUN cat /etc/sudoers
RUN useradd -ms /bin/bash spot
RUN echo spot:spot | chpasswd
RUN adduser spot sudo
USER spot
WORKDIR /home/spot
RUN rosdep update -y
RUN rosdep update -y --include-eol-distros

# get dummy workspace to install dpeendent packages
RUN mkdir -p /tmp/ws/src/jsk_robot/jsk_spot_robot/jsk_spot_startup /tmp/ws/src/jsk_robot/jsk_spot_robot/spoteus
COPY src/jsk_robot/jsk_spot_robot/jsk_spot_startup/package.xml /tmp/ws/src/jsk_robot/jsk_spot_robot/jsk_spot_startup/
COPY src/jsk_robot/jsk_spot_robot/spoteus/package.xml /tmp/ws/src/jsk_robot/jsk_spot_robot/spoteus/
COPY src/jsk_robot/jsk_spot_robot/requirements.txt /tmp/ws/src/jsk_robot/jsk_spot_robot/
# setup catkin develeopment environment with mounted workspace
RUN mkdir -p /tmp/ws
COPY package.tar /tmp/
RUN tar -C /tmp/ws/ -xvf /tmp/package.tar

# install pip3 dependencies
RUN pip3 install pip==21.3.1
Expand All @@ -36,18 +46,21 @@ RUN pip3 install wrapt==1.12.1 six==1.15.0 PyJWT==2.0.0 numpy==1.19.4 grpcio==1.
# install python requirements
RUN pip3 install -r /tmp/ws/src/jsk_robot/jsk_spot_robot/requirements.txt

# rosdep install
RUN rosdep install -y -r --from-paths /tmp/ws/src --ignore-src --rosdistro melodic || echo "OK"
# # rosdep install
# RUN sudo apt-get update && rosdep install -y -r --from-paths /tmp/ws/src --ignore-src --rosdistro melodic || echo "OK"

#####
## Initialize catkin workspace after wstool merge and update with jsk_spot_robot/jsk_spot_driver.rosinstall
#####
FROM base_build AS pre_build

# setup catkin develeopment environment with mounted workspace
COPY package.xml.tar /tmp/
RUN tar -C /tmp/ws/ -xvf /tmp/package.xml.tar
RUN rosdep install -y -r --from-paths /tmp/ --ignore-src --rosdistro melodic || echo "OK"
COPY package.tar /tmp/
RUN tar -C /tmp/ws/ -xvf /tmp/package.tar
RUN sudo apt-get update && rosdep install -y -r --from-paths /tmp/ --ignore-src --rosdistro melodic || echo "OK"
# rosdep install for python3
RUN sudo apt-get update && ROS_PYTHON_VERSION=3 rosdep install -y -r --skip-keys="python3-catkin-pkg python3-catkin-tools python3-rosinstall python3-rosdep" --from-paths /tmp/ --ignore-src --rosdistro melodic || echo "OK"

##
## 'RUN --mount' called everytime when conttnes of spot/ws changed, so use 'COPY'
#RUN --mount=type=bind,source=/,target=/home/spot/ws cd ws && rosdep install -y -r --from-paths src --ignore-src --rosdistro melodic || echo "OK"
Expand All @@ -57,19 +70,16 @@ RUN rosdep install -y -r --from-paths /tmp/ --ignore-src --rosdistro melodic ||
## User preferences for developent tools
#####
FROM pre_build AS dev_build
RUN sudo apt install -y -q python-catkin-tools less emacs vim

RUN sudo apt install -y -q bluez bluez-tools

RUN echo "#!/bin/bash" > /home/spot/ros_entrypoint.sh && \
echo "set -e" >> /home/spot/ros_entrypoint.sh && \
echo "source /opt/ros/melodic/setup.bash --" >> /home/spot/ros_entrypoint.sh && \
echo "source /home/spot/ws/devel/setup.bash --" >> /home/spot/ros_entrypoint.sh && \
echo "[ -e /home/spot/ws/install/setup.bash ] && source /home/spot/ws/install/setup.bash" >> /home/spot/ros_entrypoint.sh && \
echo "sudo service dbus start" >> /home/spot/ros_entrypoint.sh && \
echo "sudo bluetoothd &" >> /home/spot/ros_entrypoint.sh && \
echo "exec \"\$@\"" >> /home/spot/ros_entrypoint.sh

RUN chmod u+x /home/spot/ros_entrypoint.sh
RUN chmod 0777 /home/spot/ros_entrypoint.sh

### FIXME ros_entrypoint did not work with roscd
RUN echo "source /opt/ros/melodic/share/rosbash/rosbash" >> ~/.bashrc
Expand All @@ -78,3 +88,31 @@ ENV TZ=Asia/Tokyo

ENTRYPOINT ["/home/spot/ros_entrypoint.sh"]
CMD ["bash"]

FROM dev_build AS user_build

ARG USER
ENV USER ${USER:-spot}
ARG UID
ENV UID ${UID:-1000}
ARG GID
ENV GID ${GID:-1000}
RUN sudo addgroup --gid ${GID} ${USER}
RUN sudo adduser --disabled-password --gecos '' --uid ${UID} --gid ${GID} ${USER}
RUN sudo adduser ${USER} sudo
USER ${USER}

RUN echo "#!/bin/bash" > /home/${USER}/ros_entrypoint.sh && \
echo "set -e" >> /home/${USER}/ros_entrypoint.sh && \
echo "source /opt/ros/melodic/setup.bash --" >> /home/${USER}/ros_entrypoint.sh && \
echo "source /home/spot/ws/install/setup.bash --" >> /home/${USER}/ros_entrypoint.sh && \
echo "[ -e /home/${USER}/ws/devel/setup.bash ] && source /home/${USER}/ws/devel/setup.bash --" >> /home/${USER}/ros_entrypoint.sh && \
echo "exec \"\$@\"" >> /home/${USER}/ros_entrypoint.sh

RUN chmod 0777 /home/${USER}/ros_entrypoint.sh

RUN echo "source /opt/ros/melodic/share/rosbash/rosbash" >> ~/.bashrc

## FIXME @@HOME@@ is replaced by create_src_tree_tar in Makefile
ENTRYPOINT ["@@HOME@@/ros_entrypoint.sh"]
CMD ["bash"]
113 changes: 92 additions & 21 deletions jsk_spot_robot/coreio/base/Makefile
Original file line number Diff line number Diff line change
@@ -1,47 +1,118 @@
all: $(HOME)/bash.sh
@echo "make build: build docker for spot user"
@echo "make build"

$(HOME)/bash.sh:
echo "#!/bin/bash\n\ncd ~/spot_driver_ws/src/jsk_robot/jsk_spot_robot/coreio/base\nmake shell\n" > $(HOME)/bash.sh
echo "#!/bin/bash\n\ncd $(CURDIR)\nmake shell\n" > $(HOME)/bash.sh
chmod u+x $(HOME)/bash.sh


WS_ROOT=$(abspath $(CURDIR)/../../../../../)

HOSTNAME=$(shell hostname)
IPADDRESS=$(shell dig +short $(HOSTNAME).jsk.imi.i.u-tokyo.ac.jp)

ifeq ($(shell id -u $$USER),1000) ## This is dev(uid=1000) setting
DOCKER_USER=spot
DOCKER_TARGET_NAME=spot_dev_env
$(info "This is dev setting, create $(DOCKER_TARGET_NAME)")
ifneq ($(WS_ROOT),$(HOME)/spot_dev_env)
$(info "We assume WS_ROOT to $(HOME)/spot_dev_env, please setup as follows")
$(info "$ mkdir -p ~/spot_dev_env/src")
$(info "$ cd ~/spot_dev_env/src")
$(info "$ git clone $(shell git ls-remote --get-url) -b $(shell git branch | grep ^* | sed s/\*\ // )")
$(error "")
endif
else
DOCKER_USER=$(USER)
DOCKER_TARGET_NAME=$(USER)_dev_env
$(info "This is user setting, create $(DOCKER_TARGET_NAME)")
endif

define run_uid_not_equal
ifeq ($(shell id -u $$USER),${1})
$$(info "${2}")
$$(error "Target '$@' need to run except uid ${1} ($(shell id -un ${1})), your current uid is $(shell id -u $$USER) ($(shell echo $$USER))")
endif
endef
define run_uid_equal
ifneq ($(shell id -u $$USER),${1})
$$(info "${2}")
$$(error "Target '$@' need to run with uid ${1} ($(shell id -un ${1})), your current uid is $(shell id -u $$USER) ($(shell echo $$USER))")
endif
endef

define run
docker run --rm --privileged --hostname strelka --add-host strelka:133.11.216.166 --add-host strelka.jsk.imi.i.u-tokyo.ac.jp:133.11.216.166 --network=host --device=/dev/input -v $(WS_ROOT):/home/spot/ws -v $(HOME)/.ros:/home/spot/.ros -w /home/spot/ws -ti dev_env ${1};
docker run --rm --privileged --hostname $(HOSTNAME)-core-io --add-host $(HOSTNAME)-core-io:$(IPADDRESS) --add-host $(HOSTNAME)-core-io.jsk.imi.i.u-tokyo.ac.jp:$(IPADDRESS) --network=host -u=$(shell id -u $$USER):$(shell id -g $$USER) --group-add sudo --device=/dev/input -v /home/$(shell id -un 1000)/spot_dev_env:/home/spot/ws -v $(WS_ROOT):/home/$(DOCKER_USER)/ws -v $(HOME)/.ros:/home/$(DOCKER_USER)/.ros -v $(HOME)/.config:/home/$(DOCKER_USER)/.config -w /home/$(DOCKER_USER)/ws -ti $(DOCKER_TARGET_NAME) ${1};
endef

define create_src_tree_tar
cp Dockerfile $(WS_ROOT); sed -i 's+@@HOME@@+$(HOME)+' $(WS_ROOT)/Dockerfile; (cd $(WS_ROOT); find src -iname 'package.xml' -o -path '*jsk_spot_robot/requirements.txt' | tar cf package.tar -T -);
endef
define docker_run
${1}
define delete_src_tree_tar
rm $(WS_ROOT)/Dockerfile $(WS_ROOT)/package.tar;
endef

pre_build:
# setup workspace ( clone source code from jsk_spot_draiver.rosinstall, rosdep install, wstool )
base_build:
$(eval $(call run_uid_equal,1000,This target requires dev setting with uid 1000))
# make .ros file
mkdir -p ~/.ros
# create tar file to pass package.xml under jsk_spot_robot, so that pip3 install requirements.txt
$(call create_src_tree_tar)
# build base file
cp Dockerfile $(WS_ROOT)
cd $(WS_ROOT); DOCKER_BUILDKIT=1 docker build --target base_build --progress=plain --network=host -t dev_env -f Dockerfile .
$(call run, /bin/ls -al src)
# copy workspaces
cd $(WS_ROOT); DOCKER_BUILDKIT=1 docker build --target base_build --progress=plain --network=host -t spot_dev_env -f Dockerfile .
# run rosdep update
$(call run, bash -c '[ -e /etc/ros/rosdep/sources.list.d/ ] || rosdep update -y --include-eol-distros')
# create workspace from jsk_spot_driver.rosinstall
if [ ! -e $(WS_ROOT)/src/.rosinstall ]; then $(call run, wstool init src) fi
$(call run, wstool merge -t src src/jsk_robot/jsk_spot_robot/jsk_spot_driver.rosinstall)
$(call run, wstool update -t src)
# rosdep install all
cd $(WS_ROOT); DOCKER_BUILDKIT=1 docker build --target pre_build --progress=plain --network=host -t dev_env -f Dockerfile .
rm $(WS_ROOT)/Dockerfile
# delete package.tar
$(call delete_src_tree_tar)

dev_build:
cp Dockerfile $(WS_ROOT)
cd $(WS_ROOT); [ -e package.xml.tar ] || find src -iname 'package.xml' | tar cf package.xml.tar -T -
cd $(WS_ROOT); DOCKER_BUILDKIT=1 docker build --target dev_build --progress=plain --network=host -t dev_env -f Dockerfile .
rm $(WS_ROOT)/Dockerfile $(WS_ROOT)/package.xml.tar
# run rosdep install
pre_build: base_build
$(eval $(call run_uid_equal,1000,This target requires dev setting with uid 1000))
# create tarfile to pass package.xm under $($WS_ROOT), so that rosdep install finds necessary dependency list
$(call create_src_tree_tar)
# rosdep install
cd $(WS_ROOT); DOCKER_BUILDKIT=1 docker build --target pre_build --progress=plain --network=host -t spot_dev_env -f Dockerfile .
# delete package.tar
$(call delete_src_tree_tar)

catkin_build:
# install dev tools, ros_entrypoint.sh
dev_build: pre_build
$(eval $(call run_uid_equal,1000,This target requires dev setting with uid 1000))
# dev_build does not use package.xml
$(call create_src_tree_tar)
cd $(WS_ROOT); DOCKER_BUILDKIT=1 docker build --target dev_build --progress=plain --network=host -t spot_dev_env -f Dockerfile .
# delete package.tar
$(call delete_src_tree_tar)

# run user build
user_build:
$(eval $(call run_uid_not_equal,1000,This target requires user setting, except uid 1000))
$(call create_src_tree_tar)
cd $(WS_ROOT); DOCKER_BUILDKIT=1 docker build --target user_build --progress=plain --network=host -t $(shell echo $$USER)_dev_env --build-arg USER=$$USER --build-arg UID=$(shell id -u $$USER) --build-arg GID=$(shell id -g $$USER) -f Dockerfile .

# run catkin build
catkin_config:
$(call run, catkin init)
$(call run, catkin config --cmake-args -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=/usr/bin/python3 -DPYTHON_INCLUDE_DIR=/usr/include/python3.6m -DPYTHON_LIBRARY=/usr/lib/aarch64-linux-gnu/libpython3.6m.so.1)
$(call run, catkin build)
$(call run, catkin config $(CATKIN_CONFIG) --cmake-args -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=/usr/bin/python3 -DPYTHON_INCLUDE_DIR=/usr/include/python3.6m -DPYTHON_LIBRARY=/usr/lib/aarch64-linux-gnu/libpython3.6m.so.1)

catkin_build:
$(call run, catkin build)

# run all build
build:
ifeq ($(shell id -u $$USER),1000) ## This is dev(uid=1000) setting
make dev_build
make catkin_config CATKIN_CONFIG='--merge-install --blacklist test_tf2'
make catkin_build
else
make user_build
make catkin_config
endif
shell:
$(call run, bash)

Expand Down

0 comments on commit 2e17982

Please sign in to comment.