Skip to content

Instantly share code, notes, and snippets.

@rwcitek
Last active November 13, 2025 05:14
Show Gist options
  • Select an option

  • Save rwcitek/1a03bfd7b59595f4e1e36f8dc22cf393 to your computer and use it in GitHub Desktop.

Select an option

Save rwcitek/1a03bfd7b59595f4e1e36f8dc22cf393 to your computer and use it in GitHub Desktop.

This file shows how one can configure a Docker instance to create a serverless function on Digital Ocean. Rather than running doctl auth init ... to set up a config.yaml file that holds the API token, the container exec command passes in an environment variable that contains the token. In that way, the container never has the token on persistent storage. That means the instance could be committed to an image without having credentials in the image. It also means the commands in the Here-Doc could be used as as a template to create a Dockerfile in the future.

From DO function docs

First, create a Personal Accesss Token ( PAT )

Create a Docker container

# Set Digital Ocean API token
DO_TOKEN="{insert Digital Ocean API token}"

# Ensure instance doesn't exist
docker container stop digital_ocean ; docker container rm digital_ocean ; sleep 1

# Run instance in the background
docker run -d --name digital_ocean ubuntu:22.04 sleep inf ; sleep 1

# Configure the instance
<<'eof' docker exec -e DO_TOKEN="${DO_TOKEN}" -i digital_ocean /bin/bash
  export DEBIAN_FRONTEND=noninteractive

  # Install utilities
  apt-get update
  apt-get install -y wget curl less tree vim jq file git rename

  # Install doctl
  cd /tmp/
  curl -L -O https://github.com/digitalocean/doctl/releases/download/v1.84.0/doctl-1.84.0-linux-amd64.tar.gz
  tar -xf ./doctl-1.84.0-linux-amd64.tar.gz
  mv ./doctl /usr/local/bin
  
  # Configure an alias file
  echo alias doctl="'"'doctl --access-token "${DO_TOKEN}" '"'" > ~/.bash_aliases 

  # Install the serverless capability for doctl
  mkdir -p ~/.config/doctl
  doctl --access-token "${DO_TOKEN}" serverless install
eof

(Optional) At this point one could commit the instance to an image.

docker container commit digital_ocean digital_ocean:v01

Once the instance is configured, exec into it.

# Exec into the instance
docker exec -e DO_TOKEN="${DO_TOKEN}" -it digital_ocean /bin/bash

Javascript function

Once in the instance, create, run, and remove a function

# For javascript ...
# setup name space and sample function
cd
doctl serverless namespaces create --label example-namespace --region nyc1
doctl serverless init --language js example-project
tree example-project
echo >> example-project/packages/sample/hello/hello.js
cat -n example-project/packages/sample/hello/hello.js

# deploy and test function
doctl serverless deploy example-project
doctl serverless functions invoke sample/hello
doctl serverless functions invoke sample/hello -p name:DeepDiveCoding

# delete function and namespace
doctl serverless undeploy sample/hello
doctl serverless namespaces delete -f example-namespace

Python function: hello world

# For Python ...
# setup name space and sample function
cd
doctl serverless namespaces create --label example-namespace --region nyc1
doctl serverless init --language python example-project-python
tree example-project-python
echo >> example-project-python/packages/sample/hello/hello.py 
cat -n example-project-python/packages/sample/hello/hello.py 

# deploy and test function
doctl serverless deploy example-project-python
doctl serverless functions invoke sample/hello
doctl serverless functions invoke sample/hello -p name:DeepDiveCoding

# delete function and namespace
doctl serverless undeploy sample/hello
doctl serverless namespaces delete -f example-namespace

Python function: jokes

Modified from: https://github.com/digitalocean/sample-functions-python-jokes

# For Python jokes ...
# setup name space and sample function
cd
doctl serverless namespaces create --label jokes --region nyc1
git clone https://github.com/digitalocean/sample-functions-python-jokes.git
rm -rf sample-functions-python-jokes/{.git/,.do/,README.md}
tree -a sample-functions-python-jokes

# deploy and test function
doctl serverless deploy sample-functions-python-jokes --remote-build
doctl serverless functions invoke joke/joke

# delete function and namespace
doctl serverless undeploy joke/joke
doctl serverless namespaces delete -f jokes

Python function: jokes de-novo

# make folder structure
mkdir -p from-scratch/packages/de-novo/de-novo

# create project.yml
<<'eof' cat > from-scratch/project.yml
packages:
  - name: de-novo
    actions:
      - name: de-novo
        runtime: 'python:default'
eof

# create requirements file
<< 'eof' cat > from-scratch/packages/de-novo/de-novo/requirements.txt 
pyjokes==0.6.0 
eof

# create build script to load requirements
<< 'eof' cat > from-scratch/packages/de-novo/de-novo/build.sh
#!/bin/bash

set -e

virtualenv --without-pip virtualenv
pip install -r requirements.txt --target virtualenv/lib/python3.9/site-packages
eof
chmod +x from-scratch/packages/de-novo/de-novo/build.sh

# create python script
<< 'eof' cat > from-scratch/packages/de-novo/de-novo/__main__.py
import pyjokes

def main(args):
  joke = pyjokes.get_joke()
  return {
    'body': {
      'response_type': 'in_channel',
      'text': joke
    }
  }
eof

# setup name space
doctl serverless namespaces create --label de-novo --region nyc1

# deploy and test function
doctl serverless deploy from-scratch --remote-build
doctl serverless functions invoke de-novo/de-novo

# delete function and namespace
doctl serverless undeploy de-novo/de-novo
doctl serverless namespaces delete -f de-novo

Incuding Extra Data

Including extra data allows one to include pickle files, data sets, models, etc. in the function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment