This is a sample API using the Docker Python Sandbox library.
- Node
- NPM
- Docker
- Clone this repository
- Pull the docker image used by the sandbox:
docker pull christophetd/docker-sandbox
- Copy the sample configuration file:
cp api/config.js.sample api/config.js
- Run
npm start
- Navigate to
http://server-ip:3000
- Enjoy!
Requires:
- A header
Content-Type: application/json
- A header
X-API-Key: secret api key
(seeapi/config.js
) - A body of the form
{ "code": "code to execute" }
cURL example:
curl -X POST \
-H "Content-Type: application/json" \
-H "X-API-Key: sdkljf56789#KT34_" \
-d '{ "code": "print \"Hello, world!\" " }' \
localhost:3000/compile
{
"isError":false,
"stderr":"",
"stdout":"Hello, world!\n",
"combined":"Hello, world!\n",
"killedByContainer":false
}
See the Docker Sandbox library documentation to know more about the API response format.
This application showcases an API that should be private. It implements basic security mechanisms that are configurable in the configuration file:
- rate limitation
- limiting the requests to certain IPs
- authenticating the requests with a secret key
Schema of a proposed architecture:
You should NOT run this as root.
Let me say it again. You should NOT run this as root.
But by default, a non-root user won't be able to use Docker and will cause the Docker Sandbox Library to fail:
error: Error: connect EACCESS /var/run/docker.sock
The solution for that is to create a separate user to run the API, and to add it to the docker
group. This will allow him to access the Docker socket.
Example on how to do this:
mkdir /home/docker # Create a home directory
useradd --system --home /home/docker docker-api # Create the user
chown docker-api:docker-api /home/docker # Give user ownership of his home directory
usermod -a -G docker docker-api # Add the user to the 'docker' group (automatically created by docker)
Then, you'll need to log in as this user using:
sudo -Hu docker-api bash
And to install the required dependencies if needed (see Installation section). Then, you can run the API using
npm start
Or using PM2
which pm2 >/dev/null || npm install -g pm2 # Install pm2 if it is not installed
pm2 start pm2.json
If you have the possibility to do so, create a private network containing your backend and the server running this API, so the API server is only accessible from your backend. You can do this easily for instance using the [Digital Ocean private network feature] (https://www.digitalocean.com/community/tutorials/how-to-set-up-and-use-digitalocean-private-networking)
If you don't have the possibility to do this, I'd recommend the following firewall rules on the API server (examples using ufw)
apt-get install ufw
# By default, reject incoming connections
ufw default deny incoming
# By default, reject outgoing connections (optional, more restrictive, and you'll need disable it e.g. to make updates or install stuff)
ufw default deny outgoing
# Allow SSH connections
ufw allow ssh
# Open the port on which the API will be listening and make it accessible from your backend server
ufw allow from BACKEND_SERVER_IP to any port 3000
# Enable ufw
ufw enable