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 )
# 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:v01Once the instance is configured, exec into it.
# Exec into the instance
docker exec -e DO_TOKEN="${DO_TOKEN}" -it digital_ocean /bin/bashOnce 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# 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-namespaceModified 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# 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-novoIncluding extra data allows one to include pickle files, data sets, models, etc. in the function.