├── .gitignore
├── .vscode
├── data
│ └── Machine
│ │ └── settings.json
├── c_cpp_properties.json
├── settings.json
└── tasks.json
├── .devcontainer
├── compile_flags.txt
├── templates
│ ├── model.urdf.xacro
│ ├── launchfile.launch
│ └── rosnode.cpp
├── build.sh
├── jupyter.conf
├── code-server.conf
├── devcontainer.json
├── supervisord.conf
├── entrypoint.sh
└── sim.py
├── select-simulator.bat
├── select-simulator.sh
├── hooks
├── build
└── post_push
├── start-mutagen.sh
├── .env.sample
├── LICENSE
├── docker-compose.yml
├── .github
└── workflows
│ └── docker-image.yml
├── README.md
└── Dockerfile
/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | .vscode/ipch
3 | *~
4 |
--------------------------------------------------------------------------------
/.vscode/data/Machine/settings.json:
--------------------------------------------------------------------------------
1 | ../../settings.json
--------------------------------------------------------------------------------
/.devcontainer/compile_flags.txt:
--------------------------------------------------------------------------------
1 | -c
2 | -I/opt/ros/$ROS_DISTRO/include
3 | -std=c++11
4 | -fno-exceptions
--------------------------------------------------------------------------------
/select-simulator.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | docker run -ti --rm -v %cd%:/work devrt/simulator-index
3 | pause
--------------------------------------------------------------------------------
/select-simulator.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | docker pull devrt/simulator-index
3 | docker run -ti --rm -v $(pwd):/work devrt/simulator-index
4 |
--------------------------------------------------------------------------------
/.devcontainer/templates/model.urdf.xacro:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/hooks/build:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | BASE_TAG=${DOCKER_TAG%"-desktop"}
3 | docker build --build-arg BASE_IMAGE=ros:${BASE_TAG} -f Dockerfile -t $IMAGE_NAME .
4 |
--------------------------------------------------------------------------------
/start-mutagen.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | mutagen create \
4 | --symlink-mode ignore \
5 | src docker://$(docker-compose ps -q workspace)/workspace/src
6 |
--------------------------------------------------------------------------------
/hooks/post_push:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [ "$DOCKER_TAG" == "melodic-desktop" ]; then
4 | docker tag $IMAGE_NAME $DOCKER_REPO:latest
5 | docker push $DOCKER_REPO:latest
6 | fi
7 |
--------------------------------------------------------------------------------
/.env.sample:
--------------------------------------------------------------------------------
1 | HTTP_PROXY="http://example.com:8080/"
2 | HTTPS_PROXY="http://example.com:8080/"
3 | _JAVA_OPTIONS="-Dhttp.proxyHost=example.com -Dhttp.proxyPort=8080 -Dhttps.proxyHost=example.com -Dhttps.proxyPort=8080"
--------------------------------------------------------------------------------
/.devcontainer/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | for dist in melodic noetic
4 | do
5 | docker pull ros:$dist
6 | docker build --build-arg BASE_IMAGE=ros:$dist -f Dockerfile -t devrt/ros-devcontainer-vscode:$dist-desktop .
7 | done
--------------------------------------------------------------------------------
/.devcontainer/templates/launchfile.launch:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/.devcontainer/jupyter.conf:
--------------------------------------------------------------------------------
1 | [program:jupyter]
2 | command=/entrypoint.sh jupyter notebook --ip=0.0.0.0 --no-browser --NotebookApp.notebook_dir='/workspace' --NotebookApp.token='' --NotebookApp.password=''
3 | user=developer
4 | directory=/workspace
5 | environment=ROS_DISTRO=%(ENV_ROS_DISTRO)s
6 | autostart=true
7 | autorestart=true
8 | stdout_logfile=/dev/stdout
9 | stdout_logfile_maxbytes=0
10 | stderr_logfile=/dev/stderr
11 | stderr_logfile_maxbytes=0
12 |
--------------------------------------------------------------------------------
/.devcontainer/code-server.conf:
--------------------------------------------------------------------------------
1 | [program:code-server]
2 | command=code serve-web --host 0.0.0.0 --port 3000 --without-connection-token --accept-server-license-terms
3 | autostart=true
4 | autorestart=true
5 | autostart=true
6 | autorestart=true
7 | stdout_logfile=/dev/stdout
8 | stdout_logfile_maxbytes=0
9 | stderr_logfile=/dev/stderr
10 | stderr_logfile_maxbytes=0
11 | user=developer
12 | directory=/home/developer
13 | environment=HOME=/home/developer,ROS_DISTRO=%(ENV_ROS_DISTRO)s,DONT_PROMPT_WSL_INSTALL=1
--------------------------------------------------------------------------------
/.devcontainer/templates/rosnode.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | int main(int argc, char **argv)
5 | {
6 | ros::init(argc, argv, "node_name");
7 | ros::NodeHandle n;
8 | std_msgs::String msg;
9 | ros::Publisher pub = n.advertise("topic_name", 1000);
10 | ros::Rate rate(10);
11 |
12 | while (ros::ok())
13 | {
14 | msg.data = "";
15 | pub.publish(msg);
16 |
17 | ros::spinOnce();
18 | rate.sleep();
19 | }
20 |
21 | return 0;
22 | }
23 |
--------------------------------------------------------------------------------
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ROS devcontainer for vscode",
3 | "dockerComposeFile": [
4 | "../docker-compose.yml"
5 | ],
6 | "service": "workspace",
7 | "workspaceFolder": "/workspace",
8 | "shutdownAction": "stopCompose",
9 | "customizations": {
10 | "vscode": {
11 | "extensions": [
12 | "ms-vscode.cpptools",
13 | "ms-python.python",
14 | "ajshort.msg",
15 | "twxs.cmake",
16 | "redhat.vscode-xml",
17 | "actboy168.tasks",
18 | "brpaz.file-templates"
19 | ]
20 | }
21 | },
22 | //"appPort": [80],
23 | }
--------------------------------------------------------------------------------
/.devcontainer/supervisord.conf:
--------------------------------------------------------------------------------
1 | [unix_http_server]
2 | file=/var/run/supervisor.sock
3 | chmod=0700
4 |
5 | [inet_http_server]
6 | port = :9001
7 |
8 | [supervisord]
9 | nodaemon=true
10 |
11 | [rpcinterface:supervisor]
12 | supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
13 |
14 | [rpcinterface:twiddler]
15 | supervisor.rpcinterface_factory = supervisor_twiddler.rpcinterface:make_twiddler_rpcinterface
16 |
17 | [supervisorctl]
18 | serverurl=unix:///var/run/supervisor.sock
19 |
20 | [include]
21 | files = /etc/supervisor/conf.d/*.conf
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Software License Agreement (Apache License)
2 |
3 | Copyright 2020 MID Academic Promotions, Inc.
4 |
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 |
9 | http://www.apache.org/licenses/LICENSE-2.0
10 |
11 | Unless required by applicable law or agreed to in writing, software
12 | distributed under the License is distributed on an "AS IS" BASIS,
13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | See the License for the specific language governing permissions and
15 | limitations under the License.
16 |
--------------------------------------------------------------------------------
/.vscode/c_cpp_properties.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [{
3 | "name": "Linux",
4 | "includePath": [
5 | "${workspaceFolder}/**",
6 | "/opt/ros/${env:ROS_DISTRO}/include/**",
7 | "/usr/include/**"
8 | ],
9 | "browse": {
10 | "path": [
11 | "${workspaceFolder}",
12 | "/opt/ros/${env:ROS_DISTRO}/include",
13 | "/usr/include"
14 | ]
15 | },
16 | "defines": [],
17 | "compilerPath": "/usr/bin/g++",
18 | "cStandard": "c11",
19 | "cppStandard": "c++17",
20 | "intelliSenseMode": "gcc-x64"
21 | }],
22 | "version": 4
23 | }
--------------------------------------------------------------------------------
/.devcontainer/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -e
2 |
3 | USER_ID=$(id -u)
4 | GROUP_ID=$(id -g)
5 |
6 | sudo usermod -u $USER_ID -o -m -d /home/developer developer > /dev/null 2>&1
7 | sudo groupmod -g $GROUP_ID developer > /dev/null 2>&1
8 | sudo chown -R developer:developer /workspace
9 |
10 | ln -sfn /home/developer/.vscode /workspace/.vscode
11 |
12 | rm -f /workspace/compile_flags.txt || true
13 | sed -e 's@\$ROS_DISTRO@'"$ROS_DISTRO"'@' /home/developer/compile_flags.txt > /workspace/compile_flags.txt
14 |
15 | ln -sfn /workspace /home/developer/workspace
16 |
17 | source /opt/ros/$ROS_DISTRO/setup.bash
18 |
19 | mkdir -p /workspace/src && cd /workspace/src && catkin_init_workspace || true
20 |
21 | cd /home/developer
22 |
23 | exec $@
24 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2.3'
2 | services:
3 | xserver:
4 | image: devrt/xserver
5 | ipc: host
6 | security_opt:
7 | - seccomp:unconfined
8 | ports:
9 | - "3000:80"
10 | healthcheck:
11 | test: ["CMD-SHELL", "test -e /tmp/.X11-unix/X0"]
12 | interval: "1s"
13 | retries: 20
14 | simulator:
15 | image: devrt/simulator-empty
16 | ipc: host
17 | security_opt:
18 | - seccomp:unconfined
19 | environment:
20 | - DISPLAY=:0
21 | volumes_from:
22 | - xserver
23 | depends_on:
24 | - xserver
25 | workspace:
26 | # env_file:
27 | # - .env
28 | image: devrt/ros-devcontainer-vscode:noetic-desktop
29 | ipc: host
30 | security_opt:
31 | - seccomp:unconfined
32 | ports:
33 | - "3001:3000"
34 | - "3002:8888"
35 | volumes:
36 | - workspace:/workspace
37 | environment:
38 | - DISPLAY=:0
39 | - ROS_MASTER_URI=http://simulator:11311/
40 | volumes_from:
41 | - xserver
42 | - simulator
43 | depends_on:
44 | - xserver
45 | volumes:
46 | workspace:
47 |
--------------------------------------------------------------------------------
/.github/workflows/docker-image.yml:
--------------------------------------------------------------------------------
1 | name: Docker Image CI
2 |
3 | on:
4 | push:
5 | branches: [ "master" ]
6 | pull_request:
7 | branches: [ "master" ]
8 |
9 | jobs:
10 | build:
11 | name: build and publish
12 | runs-on: ubuntu-latest
13 | strategy:
14 | matrix:
15 | version: [noetic]
16 | steps:
17 | - name: Checkout
18 | uses: actions/checkout@v4
19 | - name: Set up QEMU
20 | uses: docker/setup-qemu-action@v3
21 | - name: Set up Docker Buildx
22 | uses: docker/setup-buildx-action@v3
23 | - name: Login to Docker Hub
24 | uses: docker/login-action@v3
25 | with:
26 | username: ${{ secrets.DOCKERHUB_USERNAME }}
27 | password: ${{ secrets.DOCKERHUB_TOKEN }}
28 | - name: Build and push
29 | uses: docker/build-push-action@v5
30 | with:
31 | platforms: linux/arm64/v8,linux/amd64
32 | build-args: |
33 | BASE_IMAGE=ros:${{ matrix.version }}
34 | push: true
35 | tags: devrt/ros-devcontainer-vscode:${{ matrix.version }}-desktop
36 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "workbench.colorTheme": "Monokai",
3 | "fileTemplates.templates_dir": "/home/developer/templates",
4 | "files.associations": {
5 | "*.launch": "xml",
6 | "*.launch.xml": "xml",
7 | "*.test": "xml",
8 | "*.urdf.xacro": "xml",
9 | "*.urdf": "xml",
10 | "model.config": "xml",
11 | "*.sdf": "xml",
12 | "*.world": "xml"
13 | },
14 | "xml.fileAssociations": [
15 | {
16 | "systemId": "/opt/xsd/package.xml/package_format2.xsd",
17 | "pattern": "package.xml"
18 | },
19 | {
20 | "systemId": "/opt/xsd/roslaunch/roslaunch.xsd",
21 | "pattern": "**/*.launch"
22 | },
23 | {
24 | "systemId": "/opt/xsd/roslaunch/roslaunch.xsd",
25 | "pattern": "**/*.test"
26 | },
27 | {
28 | "systemId": "/opt/xsd/ros2launch/launch.0.1.1.xsd",
29 | "pattern": "**/*.launch.xml"
30 | },
31 | {
32 | "systemId": "/opt/xsd/urdf/urdf.xsd",
33 | "pattern": "**/*.urdf.xacro"
34 | },
35 | {
36 | "systemId": "/opt/xsd/urdf/urdf.xsd",
37 | "pattern": "**/*.urdf"
38 | },
39 | {
40 | "systemId": "/opt/xsd/sdf/root.xsd",
41 | "pattern": "**/*.sdf"
42 | },
43 | {
44 | "systemId": "/opt/xsd/sdf/root.xsd",
45 | "pattern": "**/*.world"
46 | }
47 | ],
48 | "C_Cpp.intelliSenseCacheSize": 0,
49 | "C_Cpp.intelliSenseEngine": "Tag Parser",
50 | "python.analysis.extraPaths": [
51 | "/opt/ros/noetic/lib/python3/dist-packages"
52 | ]
53 | }
54 |
--------------------------------------------------------------------------------
/.devcontainer/sim.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | # Utility script to control process on the simulator container
4 | # written by Yosuke Matsusaka
5 | # distributed under apache2 license
6 |
7 | import argparse
8 | import argcomplete
9 | import xmlrpclib
10 | import pprint
11 |
12 | parser = argparse.ArgumentParser()
13 | parser.add_argument('command', choices=['launch', 'reset', 'status'], help='run roslaunch or reset the simulator container')
14 | parser.add_argument('args', nargs='*', help='command arguments')
15 | parser.add_argument('-n', '--name', default='simulator', help='specify name of the process (default: simulator)')
16 | parser.add_argument('-e', '--env', default='', help='specify environment variables')
17 |
18 | argcomplete.autocomplete(parser)
19 |
20 | args = parser.parse_args()
21 |
22 | s = xmlrpclib.ServerProxy('http://simulator:9001')
23 |
24 | if args.command == 'launch':
25 | try:
26 | s.supervisor.stopProcess('simulator:{0}'.format(args.name))
27 | except xmlrpclib.Fault:
28 | pass
29 | try:
30 | s.twiddler.removeProcessFromGroup('simulator', args.name)
31 | except xmlrpclib.Fault:
32 | pass
33 | command = ['/ros_entrypoint.sh roslaunch']
34 | command.extend(args.args)
35 | s.twiddler.addProgramToGroup('simulator', args.name,
36 | {
37 | 'command': ' '.join(command),
38 | 'environment': args.env,
39 | 'autostart': 'true',
40 | 'autorestart': 'true',
41 | 'stopwaitsecs': '30',
42 | 'stdout_logfile': '/dev/stdout',
43 | 'stdout_logfile_maxbytes': '0',
44 | 'stderr_logfile': '/dev/stderr',
45 | 'stderr_logfile_maxbytes': '0'
46 | })
47 | elif args.command == 'reset':
48 | s.supervisor.stopProcess('simulator:{0}'.format(args.name))
49 | s.supervisor.startProcess('simulator:{0}'.format(args.name))
50 | elif args.command == 'status':
51 | pprint.pprint(s.supervisor.getAllProcessInfo())
52 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | // See https://go.microsoft.com/fwlink/?LinkId=733558
3 | // for the documentation about the tasks.json format
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "label": "catkin_make",
8 | "type": "shell",
9 | "command": "bash -i -c catkin_make",
10 | "group": {
11 | "kind": "build",
12 | "isDefault": true
13 | },
14 | "problemMatcher": {
15 | "fileLocation": "absolute",
16 | "pattern": {
17 | "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
18 | "file": 1,
19 | "line": 2,
20 | "column": 3,
21 | "severity": 4,
22 | "message": 5
23 | }
24 | }
25 | },
26 | {
27 | "label": "catkin_create_pkg",
28 | "type": "shell",
29 | "command": "bash -i -c 'cd src && catkin_create_pkg ${input:packageName} ${input:dependingPackages}'"
30 | },
31 | {
32 | "label": "xserver",
33 | "type": "shell",
34 | "command": "echo",
35 | "args": [
36 | "Please open http://localhost:3000/ using your favorite browser.\n(If you are using Docker Toolbox, open http://192.168.99.100:3000/ instead)"
37 | ]
38 | },
39 | {
40 | "label": "roscore",
41 | "type": "shell",
42 | "command": "bash -i -c roscore",
43 | "presentation": {
44 | "reveal": "always",
45 | "panel": "new"
46 | }
47 | },
48 | {
49 | "label": "rviz",
50 | "type": "shell",
51 | "command": "bash -i -c 'rosrun rviz rviz'",
52 | "presentation": {
53 | "reveal": "always",
54 | "panel": "new"
55 | }
56 | }
57 | ],
58 | "inputs": [
59 | {
60 | "id": "packageName",
61 | "type": "promptString",
62 | "description": "Please enter the name of new package"
63 | },
64 | {
65 | "id": "dependingPackages",
66 | "type": "promptString",
67 | "description": "Please enter name of depending packages",
68 | "default": "roscpp std_msgs"
69 | }
70 | ]
71 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ROS dev container for VSCode
2 | ----------------------------
3 | Packed with:
4 | - Preconfigured docker image for ROS development.
5 | - Browser accessible X11 server to display gazebo, rviz, rqt (runs on Windows/Mac).
6 | - Tasks definition to run catkin_make, roscore, rviz commands.
7 | - Preconfigured code completion for C++, Python, XML (package.xml, launchfiles, URDF, SDF).
8 | - Preconfigured simulation environments (Flatland, TurtleBot3, ARIAC, Virtual RobotX, UUV).
9 | - Bonus: WebIDE (code-server) with preconfigured C++, Python, XML completion.
10 |
11 | VSCode and devcontainer running on Mac:
12 | 
13 |
14 | WebIDE opened from the local browser while devcontainer is running on the remote server:
15 | 
16 |
17 | How to select simulation environment
18 | -------------------------------------
19 | You can run preconfigured simulation environment as a docker sidecar container.
20 |
21 | Enter following command to select the simulator:
22 | ```shell
23 | $ ./select-simulator.sh
24 | ```
25 |
26 | Preconfigured simulation environment currently includes: Flatland, TurtleBot3, ARIAC, Virtual RobotX, UUV.
27 |
28 | See the following index for list of current simulators:
29 |
30 | https://github.com/devrt/simulator-index/blob/master/index.yaml
31 |
32 | If you want any other simulator, let us know by submitting the issue:
33 |
34 | https://github.com/devrt/simulator-index/issues
35 |
36 | How to use the WebIDE (recommended)
37 | -------------------------------------
38 | As of writing, docker-compose support of VSCode is not so stable on all the platforms.
39 | We recommend using code-server WebIDE since it has complete VSCode function support.
40 |
41 | 1. Clone this repository:
42 | ```shell
43 | $ git clone https://github.com/devrt/ros-devcontainer-vscode.git
44 | ```
45 |
46 | 2. Enter the following command under the folder of the cloned project:
47 | ```shell
48 | $ cd ros-devcontainer-vscode
49 | $ docker-compose up
50 | ```
51 |
52 | 3. Open http://localhost:3001/ using your favorite browser.
53 |
54 | You can also use remote server to host the devcontainer (run `docker-compose up` on the remote server and open `http://[remote-server]:3001`).
55 |
56 | How to use this dev container with VSCode
57 | -----------------------------------------
58 | First, you have to install VSCode and Docker for Windows/Mac:
59 | - https://code.visualstudio.com/
60 | - https://docs.docker.com/docker-for-mac/
61 | - https://docs.docker.com/docker-for-windows/
62 |
63 | After you installed required softwares:
64 |
65 | 1. Install ["Remote Development" extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack) on your VSCode.
66 | 2. Clone this repository by using git command.
67 | 3. Click on the quick actions status bar item (green icon) in the lower left corner of the VSCode.
68 | 4. Select "Remote-Containers: Open Folder in Container..." from the command list that appears, and open the root folder of the project you just cloned.
69 | 5. You need to wait a while for container to come up (only required once).
70 |
71 | For detailed instructions, see:
72 | https://code.visualstudio.com/docs/remote/containers
73 |
74 | If you are behind the proxy
75 | -----------------------------
76 |
77 | Please apply following two settings, if you are using your PC behind the proxy.
78 |
79 | 1. Proxy setting for the Docker server.
80 |
81 | Click Docker Desktop task bar icon > Select `preference` menu item. You will see the following options:
82 |
83 | 
84 |
85 | In most cases, `System proxy` option will work. But if you have problem downloading the docker images, please try `Manual proxy configuration` option.
86 |
87 | 2. Proxy setting for the devcontainer.
88 |
89 | This setting will enable you to use the `apt-get` or the other network commands inside the devcontainer.
90 |
91 | First, open `.env.sample` file under the root folder of the cloned project.
92 | Edit the settings according to your environment.
93 | Save the file as name `.env`.
94 |
95 | Next, open `docker-compose.yml` file under the root folder of the cloned project and uncomment the following lines:
96 | ```yaml
97 | workspace:
98 | env_file:
99 | - .env
100 | ```
101 |
102 | How to reset or update the devcontainer
103 | ---------------------------------------
104 |
105 | If you want to reset the devcontainer. Please close vscode and enter the following command under the folder of the cloned project:
106 | ```shell
107 | $ docker-compose down
108 | ```
109 |
110 | If you want to update the environment to the most recent version. Please enter the following commands under the folder of the cloned project:
111 | ```shell
112 | $ git pull origin master
113 | $ docker-compose pull
114 | ```
115 |
116 | Please be noticed that the `docker-compose down` command will reset your environment including installed `.deb` packages. However, if you write `package.xml` files correctly, you can reinstall all the depending packages by entering the following two commands:
117 | ```shell
118 | $ rosdep update
119 | $ rosdep install --from-paths src --ignore-src -r -y
120 | ```
121 |
122 | How to open X11 server screen
123 | -----------------------------
124 |
125 | 1. Wait for the container to start.
126 | 2. Open http://localhost:3000/ using your favorite browser.
127 |
128 | If you are using Docker Toolbox, open the following URL instead:
129 |
130 | http://192.168.99.100:3000/
131 |
132 | If you want browser screen to be integrated with VS Code, use [Browser Preview for VS Code extension](https://marketplace.visualstudio.com/items?itemName=auchenberg.vscode-browser-preview).
133 |
134 | Created by
135 | ----------
136 | Yosuke Matsusaka (MID Academic Promotions, Inc.)
137 |
138 | License
139 | -------
140 | Code in this repository (Dockerfile, utility scripts, etc) is distributed under Apache 2.0 license.
141 |
142 | Included components are distributed under each different licenses:
143 | - Jupyter notebook: BSD
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG BASE_IMAGE=ros:noetic
2 |
3 | FROM maven:3.8 AS xsdcache
4 |
5 | # install schema-fetcher
6 | RUN apt update && \
7 | apt install -y git && \
8 | git clone --depth=1 https://github.com/mfalaize/schema-fetcher.git && \
9 | cd schema-fetcher && \
10 | sed -i 's|>1.7<|>1.8<|g' pom.xml && \
11 | mvn install
12 |
13 | # fetch XSD file for package.xml
14 | RUN mkdir -p /opt/xsd/package.xml && \
15 | java -jar schema-fetcher/target/schema-fetcher-1.0.0-SNAPSHOT.jar /opt/xsd/package.xml http://download.ros.org/schema/package_format2.xsd
16 |
17 | # fetch XSD file for roslaunch
18 | RUN mkdir -p /opt/xsd/roslaunch && \
19 | java -jar schema-fetcher/target/schema-fetcher-1.0.0-SNAPSHOT.jar /opt/xsd/roslaunch https://gist.githubusercontent.com/nalt/dfa2abc9d2e3ae4feb82ca5608090387/raw/roslaunch.xsd
20 |
21 | # fetch XSD file for ros2launch
22 | RUN mkdir -p /opt/xsd/ros2launch && \
23 | java -jar schema-fetcher/target/schema-fetcher-1.0.0-SNAPSHOT.jar /opt/xsd/ros2launch https://raw.githubusercontent.com/ros2/design/gh-pages/articles/specs/launch.0.1.1.xsd
24 |
25 | # fetch XSD files for SDF
26 | RUN mkdir -p /opt/xsd/sdf && \
27 | java -jar schema-fetcher/target/schema-fetcher-1.0.0-SNAPSHOT.jar /opt/xsd/sdf http://sdformat.org/schemas/root.xsd && \
28 | sed -i 's|http://sdformat.org/schemas/||g' /opt/xsd/sdf/*
29 |
30 | # fetch XSD file for URDF
31 | RUN mkdir -p /opt/xsd/urdf && \
32 | java -jar schema-fetcher/target/schema-fetcher-1.0.0-SNAPSHOT.jar /opt/xsd/urdf https://raw.githubusercontent.com/devrt/urdfdom/xsd-with-xacro/xsd/urdf.xsd
33 |
34 | FROM $BASE_IMAGE
35 |
36 | MAINTAINER Yosuke Matsusaka
37 |
38 | SHELL ["/bin/bash", "-c"]
39 |
40 | ENV DEBIAN_FRONTEND noninteractive
41 |
42 | # workaround to enable bash completion for apt-get
43 | # see: https://github.com/tianon/docker-brew-ubuntu-core/issues/75
44 | RUN rm /etc/apt/apt.conf.d/docker-clean
45 |
46 | # use closest mirror for apt updates
47 | RUN sed -i -e 's/http:\/\/archive/mirror:\/\/mirrors/' -e 's/http:\/\/security/mirror:\/\/mirrors/' -e 's/\/ubuntu\//\/mirrors.txt/' /etc/apt/sources.list
48 |
49 | RUN apt-get update || true && \
50 | apt-get install -y curl apt-transport-https ca-certificates && \
51 | apt-get clean
52 |
53 | # need to renew the key for some reason
54 | RUN curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | apt-key add -
55 |
56 | # OSRF distribution is better for gazebo
57 | RUN sh -c 'echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-stable `lsb_release -cs` main" > /etc/apt/sources.list.d/gazebo-stable.list' && \
58 | curl -L http://packages.osrfoundation.org/gazebo.key | apt-key add -
59 |
60 | # nice to have nodejs for web goodies
61 | RUN sh -c 'echo "deb https://deb.nodesource.com/node_14.x `lsb_release -cs` main" > /etc/apt/sources.list.d/nodesource.list' && \
62 | curl -sSL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add -
63 |
64 | # vscode
65 | RUN curl -sSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > packages.microsoft.gpg && \
66 | install -D -o root -g root -m 644 packages.microsoft.gpg /etc/apt/keyrings/packages.microsoft.gpg && \
67 | sh -c 'echo "deb [arch=amd64,arm64,armhf signed-by=/etc/apt/keyrings/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" > /etc/apt/sources.list.d/vscode.list' && \
68 | rm -f packages.microsoft.gpg
69 |
70 | # install depending packages
71 | RUN apt-get update && apt-get upgrade -y && \
72 | apt-get install -y bash-completion less wget language-pack-en code vim-tiny iputils-ping net-tools openssh-client git openjdk-8-jdk-headless nodejs sudo imagemagick byzanz python-dev libsecret-1-dev && \
73 | npm install -g yarn && \
74 | apt-get clean
75 |
76 | # basic python packages
77 | RUN if [ $(lsb_release -cs) = "focal" ]; then \
78 | apt-get update; \
79 | apt-get install -y python-is-python3 python3-catkin-tools python3-colcon-common-extensions; \
80 | apt-get clean; \
81 | curl -kL https://bootstrap.pypa.io/get-pip.py | python; \
82 | else \
83 | curl -kL https://bootstrap.pypa.io/pip/2.7/get-pip.py | python; \
84 | fi && \
85 | pip install --upgrade --ignore-installed --no-cache-dir pyassimp pylint==1.9.4 autopep8 python-language-server[all] notebook~=5.7 Pygments matplotlib ipywidgets jupyter_contrib_nbextensions nbimporter supervisor supervisor_twiddler argcomplete
86 |
87 | # jupyter extensions
88 | RUN jupyter nbextension enable --py widgetsnbextension && \
89 | jupyter contrib nbextension install --system
90 |
91 | # add non-root user
92 | RUN useradd -m developer && \
93 | echo developer ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/developer && \
94 | chmod 0440 /etc/sudoers.d/developer
95 |
96 | # install depending packages (install moveit! algorithms on the workspace side, since moveit-commander loads it from the workspace)
97 | RUN apt-get update && apt-get upgrade -y && \
98 | apt-get install -y ros-$ROS_DISTRO-desktop ros-$ROS_DISTRO-gazebo-msgs ros-$ROS_DISTRO-moveit ros-$ROS_DISTRO-moveit-commander ros-$ROS_DISTRO-moveit-ros-visualization ros-$ROS_DISTRO-trac-ik ros-$ROS_DISTRO-move-base-msgs ros-$ROS_DISTRO-ros-numpy && \
99 | apt-get clean
100 |
101 | # temporal hack to fix ros_numpy problem
102 | RUN if [ $(lsb_release -cs) = "focal" ]; then \
103 | curl -sSL https://raw.githubusercontent.com/eric-wieser/ros_numpy/master/src/ros_numpy/point_cloud2.py > /opt/ros/$ROS_DISTRO/lib/python3/dist-packages/ros_numpy/point_cloud2.py; \
104 | fi
105 |
106 | # install bio_ik
107 | RUN source /opt/ros/$ROS_DISTRO/setup.bash && \
108 | mkdir -p /bio_ik_ws/src && \
109 | cd /bio_ik_ws/src && \
110 | catkin_init_workspace && \
111 | git clone --depth=1 https://github.com/TAMS-Group/bio_ik.git && \
112 | cd .. && \
113 | catkin_make install -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/ros/$ROS_DISTRO -DCATKIN_ENABLE_TESTING=0 && \
114 | cd / && rm -r /bio_ik_ws
115 |
116 | # configure services
117 | RUN mkdir -p /etc/supervisor/conf.d
118 | COPY .devcontainer/supervisord.conf /etc/supervisor/supervisord.conf
119 | COPY .devcontainer/code-server.conf /etc/supervisor/conf.d/code-server.conf
120 | COPY .devcontainer/jupyter.conf /etc/supervisor/conf.d/jupyter.conf
121 |
122 | COPY .devcontainer/entrypoint.sh /entrypoint.sh
123 |
124 | COPY .devcontainer/sim.py /usr/bin/sim
125 |
126 | COPY --from=xsdcache /opt/xsd /opt/xsd
127 |
128 | USER developer
129 | WORKDIR /home/developer
130 |
131 | ENV HOME /home/developer
132 | ENV SHELL /bin/bash
133 |
134 | # jre is required to use XML editor extension
135 | ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64
136 |
137 | # enable bash completion
138 | RUN git clone --depth=1 https://github.com/Bash-it/bash-it.git ~/.bash_it && \
139 | ~/.bash_it/install.sh --silent && \
140 | rm ~/.bashrc.bak && \
141 | echo "source /usr/share/bash-completion/bash_completion" >> ~/.bashrc && \
142 | bash -i -c "bash-it enable completion git"
143 |
144 | RUN echo 'eval "$(register-python-argcomplete sim)"' >> ~/.bashrc
145 |
146 | RUN git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf && \
147 | ~/.fzf/install --all
148 |
149 | #RUN git clone --depth 1 https://github.com/b4b4r07/enhancd.git ~/.enhancd && \
150 | # echo "source ~/.enhancd/init.sh" >> ~/.bashrc
151 |
152 | # colorize less
153 | RUN lesspipe >> ~/.bashrc && \
154 | echo "export LESS='-R'" >> ~/.bashrc && \
155 | echo "export PYGMENTIZE_STYLE='monokai'" >> ~/.bashrc && \
156 | curl -sSL https://raw.githubusercontent.com/CoeJoder/lessfilter-pygmentize/master/.lessfilter > ~/.lessfilter && \
157 | chmod 755 ~/.lessfilter
158 |
159 | # init rosdep
160 | RUN rosdep update
161 |
162 | # global vscode config
163 | ADD .vscode /home/developer/.vscode
164 | RUN ln -s /home/developer/.vscode /home/developer/.vscode-server
165 | ADD .devcontainer/compile_flags.txt /home/developer/compile_flags.txt
166 | ADD .devcontainer/templates /home/developer/templates
167 | RUN sudo chown -R developer:developer /home/developer
168 |
169 | RUN code --install-extension ms-python.python && \
170 | code --install-extension ms-vscode.cpptools-extension-pack && \
171 | code --install-extension redhat.vscode-xml
172 |
173 | # enable jupyter extensions
174 | RUN jupyter nbextension enable hinterland/hinterland && \
175 | jupyter nbextension enable toc2/main && \
176 | jupyter nbextension enable code_prettify/autopep8 && \
177 | jupyter nbextension enable nbTranslate/main && \
178 | mkdir -p /home/developer/.ipython/profile_default && \
179 | echo "c.Completer.use_jedi = False" >> /home/developer/.ipython/profile_default/ipython_kernel_config.py
180 |
181 | # ROS goodies
182 | RUN echo "alias rte='rostopic list | fzf --preview \"rostopic echo -c {}\"'" >> ~/.bashrc
183 | RUN echo "alias rti='rostopic list | fzf --preview \"rostopic info {}\"'" >> ~/.bashrc
184 | RUN echo "alias rni='rosnode list | fzf --preview \"rosnode info {}\"'" >> ~/.bashrc
185 | RUN echo "alias rsi='rosservice list | fzf --preview \"rosservice info {}\"'" >> ~/.bashrc
186 | RUN echo "alias rmi='rosmsg list | fzf --preview \"rosmsg info {}\"'" >> ~/.bashrc
187 | RUN echo "alias rcd='roscd \$(rospack list-names | fzf --preview=\"rospack find {} && pygmentize \\\$(rospack find {})/package.xml\")'" >> ~/.bashrc
188 |
189 | # enter ROS world
190 | RUN echo "source /opt/ros/$ROS_DISTRO/setup.bash" >> ~/.bashrc
191 |
192 | EXPOSE 3000 8888
193 |
194 | ENTRYPOINT [ "/entrypoint.sh" ]
195 | CMD [ "sudo", "-E", "/usr/local/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]
196 |
--------------------------------------------------------------------------------