Library / SDK
autorope/donkeycar avatar
autorope/donkeycar

Donkeycar: the Dockerfile runs Jupyter on 0.0.0.0 with the token set to empty

Open source hardware and software platform to build a small scale self driving car.

3,513 stars1,368 forksPythonMIT

At a glance

What is it?
autorope/donkeycar is a Python self driving library for hobbyist cars whose only container recipe builds on Python 3.6, copies a setup.py that is no longer in the repository, starts a notebook server on every interface with both the password and the token disabled, and whose Jetson extra pins a numpy older than the base dependency allows.
Who is it for?
Use the library on a car you control, and do not run this container image as it stands. Two things block that.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 16 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 4, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The Dockerfile builds on Python 3.6 and copies a setup.py that is not in the repository

The container recipe in this repository starts from python:3.6. That is a December 2016 release of Python, and its end of life was December 2021.

The package metadata says otherwise. It requires Python 3.12.0 or newer and below 3.14, and its classifiers name 3.12 and 3.13. The repository also carries a file at the top level whose whole purpose is a Python 3.12 migration guide, so the project has already done that version move.

So the image base is six Python major versions behind the floor the package declares, and no amount of pip can bridge that.

The second failure is earlier in the same file. The build copies the project setup file into the image directory before installing anything. The repository's top level contains a pyproject.toml and no setup.py, and no setup.cfg either. The copy step has no source file, so the build stops before it ever reaches the install line that would have failed on the version constraint.

Two failures, both fatal, both in a file that has clearly not been touched since the packaging was modernised. That is worth knowing before you follow the README's own link to build and install documentation, because the one build recipe in the repository cannot succeed.

The rest of the recipe is also out of step: it installs a TensorFlow extra that is not among the three extras visible in the metadata, and it installs a development extra that is not visible there either.

The container starts Jupyter on every interface with the password and the token both empty

The image does not start the car software. Its command starts a notebook server, and it does so with the authentication turned off in two separate places.

The recipe first generates a notebook configuration file, then appends a line setting the notebook password to an empty string, then appends a second line setting the notebook token to an empty string. The container is then started with the notebook bound to all interfaces, on port 8888, with the flag that permits running as root.

Password and token are the two ways a notebook server decides who may run code on it. Setting both to empty is not a weaker default; it is no default. Anyone who can reach port 8888 gets a notebook, and a notebook is arbitrary code execution on that machine.

The bind address is what turns that into a network problem rather than a local one. All interfaces rather than loopback means the container is reachable from whatever network the host is attached to, and the documentation this project points you to is about hobbyist cars on a desk and Raspberry Pis on a home network, where a bridged or shared network is a normal thing to have.

Nothing in the recipe sets an allow-list, a token, or a reverse proxy in front of it. The two lines that disable authentication are the only two lines about authentication, and they are written in the imperative with no comment.

This is the single thing to fix before running this image anywhere. The failure mode is not that the notebook is unprotected in theory; it is that the container is designed to publish an unprotected notebook on a network port and the surrounding README describes a beginner-friendly setup.

The Jetson extra pins numpy 1.23 while the base requires 1.26 or newer

The package declares sixteen runtime dependencies and then three extras, one per kind of hardware: a Raspberry Pi group, a Jetson Nano group, and a personal computer group. The extras are where the interesting constraints live.

Start with the base list. It requires numpy at 1.26.0 or newer.

Now look at the Jetson Nano group. It pins numpy to the 1.23 series with an exact wildcard, and it also pins matplotlib to the 3.7 series and pandas to the 2.0 series. So the Jetson group asks for a version of numpy that is older than the minimum the base list sets.

Those two requirements cannot both be satisfied. A single numpy version has to be at least 1.26.0 and simultaneously in the 1.23 series, and no such version exists. Any attempt to install the Jetson extra on top of the base requirements gives the resolver a contradiction, and the practical result is that one of the two constraints loses: either the resolver refuses, or numpy ends up below the base floor.

The Jetson group also pins two other packages with the same exact-wildcard style while everything else in the file uses a lower bound, so the file mixes two pinning disciplines. The personal computer group does the same with a TensorFlow version and a Keras compatibility shim pinned to match it.

One more detail in the Raspberry Pi group: pandas appears twice in the same list. Duplicate entries in a dependency list are harmless to a resolver and are a decent signal that nobody has read this block end to end in a while.

The Makefile has two targets and a coverage file nothing reads

The whole make surface of this project is four lines. One target runs the tests through uv, and one builds the distribution through uv. There is no install target, no lint, no format, no docs, no development server and no clean.

Two things follow from that. First, the build and the test both go through uv, while the container recipe installs with pip and an editable flag. So the project has two package workflows, and the one in the Dockerfile is the one that cannot work.

Second, and more interesting, there is a coverage configuration file at the top level of the repository. The test target invokes pytest with no flags. A coverage configuration on disk does not turn coverage on; it only describes what to do if something turns it on. So the project ships a coverage configuration and a test target that never activates it.

That is the kind of thing that survives because the coverage report is generated by something other than the Makefile, probably a continuous integration step, and nobody removed the file when that became true. But for anyone running the tests locally, the measurement silently does not happen and the output looks identical either way.

The naming is worth one more note. The target is called tests, plural, and package, rather than test and build. Small, but it means muscle memory from other repositories does not find them, which matters more in a project whose whole pitch is that beginners can get going.

Port 8887 is exposed and the image never starts anything on it

The container recipe exposes two ports. One is 8888, commented as the port for the notebook server, which is the thing the container actually starts. The other is 8887, commented as the port for donkeycar.

Nothing in the recipe starts donkeycar. The command is a notebook server, and there is no second process, no supervisor and no entrypoint script that launches one. So the image exposes a port, and documents in a comment what that port is nominally for, and then never listens on it.

That is harmless in the narrow sense, because an exposed port with nothing behind it refuses connections. It is worth knowing for two reasons.

The first is that the comment tells you the project's intended port for the car service is 8887, which is not a number the README or the documentation pages quoted anywhere in it ever mention. So the one place the port appears in the repository is a comment in a Dockerfile for a port that does not work.

The second is what happens when someone follows that comment and publishes 8887 expecting a service. They get a connection refused, and the natural next step is to go looking for where the server is started, which is nowhere in this recipe. That search is the kind of dead end that costs an afternoon, and it is the kind of thing a one line comment saying this image does not start the car service would have prevented.

Configuring the car means editing a Python file, so a config mistake is a syntax error

The README answers the question of what you need to know with a section headed what do you need to know before starting, and answers it with nothing. It then spends the rest of the section listing things that help.

The first is Python programming, and the reasoning is unusually specific. You do not have to do any programming to use Donkeycar, the README says, because the file you edit to configure your car is a Python file, and you mostly just uncomment the sections you want to change and edit them.

So the configuration surface of this project is a commented-out Python module. That is a deliberate choice and it has a real property: the config file is type-checked and syntax-checked by the same interpreter that runs the car, which means a typo in a value is caught the same way a typo in code is.

It also means the failure mode is a traceback rather than a config error. Uncommenting a line at the wrong indentation is a syntax error in Python, not a rejected setting, and the README says as much when it tells you that you can avoid common mistakes if you know how comments and indentation work.

That is why the section then spends three paragraphs on things that have nothing to do with driving. It tells you to set up the single board computer on its own first, browse some websites, watch a video, write and save a file in a text editor, and learn to navigate a file system in a terminal. All of that is preparation for editing one commented Python file correctly, which is the real prerequisite.

The README calls the project Donkey in one sentence and Donkeycar in every other

The README is otherwise careful and quite long. It walks through what the project is, who it is for, what you need to know, the parts pipeline, the supported cameras, controllers and drivetrains, and it links out to documentation for each. This is a README written for someone who has never seen the project before.

Inside it, the project is called three different things. It is Donkeycar in the heading, in the body text, and in every documentation link. It is a python self driving library in the heading. And in the middle of the list of supported autopilots, one sentence reads that Donkey supports three kinds of autopilots, and the list that follows is the deep learning one, the GPS one and the computer vision one.

So the sentence introducing the project's three autopilots names something else. It is a slip rather than a rename, and a reader who has not met Donkey before has no way to know that Donkey and Donkeycar are the same thing.

The same sentence has a grammar slip in the controllers paragraph above it, where the README says that Donkeycar support a list of game controllers. Subject and verb disagree, in a sentence enumerating six controller families.

Those are small. The one worth repeating is the autopilot naming, because it appears at the exact point where a reader is about to choose between three things, and it is the sentence that tells them how many there are.

Three plain HTTP links and a contributor anchor with no target

The README opens with an empty link whose target is a fragment, and the fragment points at a contributors section that is not in the document. So the contributors link at the very top of the page goes nowhere.

Then the quick links. Two of the three are plain HTTP rather than HTTPS: the main site and the documentation site. The repository's own homepage field is also plain HTTP, and it uses a different hostname from the quick link, with a subdomain on one and none on the other.

For a documentation site you are about to type a command into, plain HTTP is worth more than a footnote. It means the page you read to learn how to build the car can be altered in transit without anything telling you, and the commands on it are the commands that end up with root on a single board computer.

The rest of the link surface is better. The documentation links are all HTTPS, the guides are on the documentation host rather than the main site, and each part category has its own page.

The text has its share of small errors too. It says participants can learn about technology and spells it with the letters transposed. It calls the project the Hello World of autonomous driving and transposes a vowel. It says no specific prerequisite knowledge is required and misspells prerequisite. Three separate transpositions in a document that is otherwise unusually careful.

Editorial conclusion

Use the library on a car you control, and do not run this container image as it stands. Two things block that. The recipe's base is Python 3.6 while the package requires 3.12 or newer, and it copies a setup file the repository no longer contains, so the image cannot build at all. Beyond that, the image starts a notebook server on every interface with both authentication mechanisms explicitly disabled, which is arbitrary code execution on whatever network the host sits on. If you want a container, write the recipe yourself: the project needs Python 3.12, a TensorFlow or PyTorch extra of your choosing, and a real token on anything you expose.

Frequently asked questions

What is Donkeycar?

A minimalist and modular self driving library for Python, developed for hobbyists and students, with a graphical interface and a simulator so you can experiment before building a robot. It is MIT licensed, and the package requires Python 3.12.0 or newer and below 3.14.

Which Python versions does Donkeycar support?

The package metadata requires Python 3.12.0 or newer and below 3.14, with classifiers for 3.12 and 3.13, and the repository carries a Python 3.12 migration guide at its top level. The Dockerfile in the repository, however, is based on python:3.6.

What do I need to know before using Donkeycar?

The README says no specific prerequisite knowledge is required, then lists three things that help. Python programming, because the configuration file you edit, myconfig.py, is a Python file you configure by uncommenting sections. The Raspberry Pi, if you have one set up. And the Linux command line, for installing the software and starting it.

How is a Donkeycar vehicle configured?

By editing myconfig.py, which is a Python file, uncommenting the sections you want to change. A vehicle template is a pipeline of parts that run in order on each pass through the vehicle loop, reading inputs and writing outputs, and you can write your own part and add it to a template.

What hardware does Donkeycar support?

Many kinds of camera including 3D cameras and lidar, a GPS receiver for position readings, game controllers including PS3, PS4, Xbox, Wii U, Nimbus and Logitech Bluetooth, plus a WebUI controller and an onscreen touch controller for phones. Drivetrains include the ESC with steering servo common to most RC cars, and differential drive.

What does the Donkeycar Dockerfile actually start?

A notebook server on all interfaces at port 8888, with the notebook password and the notebook token both set to empty, and the flag that allows running as root. It also exposes port 8887 for donkeycar itself, which the image's own command never starts.

Official sources

  1. autorope/donkeycar on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/autorope-donkeycar.svg)](https://hysenlabs.com/projects/autorope-donkeycar)