documents/dev/docker.md
Table of Contents
Docker
Mac Instructions
brew install colima
colima start
Commands
Container vs Image. A Docker container is a self-contained, runnable software application or service. On the other hand, a Docker image is the template loaded onto the container to run it, like a set of instructions. You store images for sharing and reuse, but you create and destroy containers over an application's lifecycle.
General
docker info
docker ps -a
Container
# runs a new command in a running conainer. interactive. tty (allocate a pseudo-TTY)
docker exec -it mycontainer sh
# creates (touch) a new file (/tmp/execWorks) inside container mycontainer in the background (-d for detached)
docker exec -d mycontainer touch /tmp/execWorks
# runs a command in a new container, pulling the image if needed and starting the container
# -d runs contaienr in detached/bg mode
# -p 8080:80 maps port 8080 of host to 80 of container
docker run -dp 8080:80 --rm docker/getting-started
# stop & remove container
docker stop <container-id>
docker rm <container-id>
Images
# uses the Dockerfile to build a new container image.
# "-t" tags the image -> human-readable name for the final image.
# "." at the end tells where to look for Dockerfile
docker build -t mycontainer .
# list & remove
docker image list
docker image rm IMAGE_ID
# tags are just human-readable aliases for the image ID
docker tag # alias to docker image tag
# create another tag using image ID
docker image tag IMAGE_ID myname/server:latest
# Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
docker image tag source_image:tag target_image:tag
# tag with ECR
docker tag ventz/whisper:latest 123456789012.dkr.ecr.us-east-1.amazonaws.com/whisper:latest
# removing a tag
docker rmi myname/server
# sharing the app / pushing an image via Elastic Container Registry (ECR)
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/whisper:latestdocker tag ventz/whisper:latest 123456789012.dkr.ecr.us-east-1.amazonaws.com/whisper:latest
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/whisper:latest
AWS ECR Containers
# build container
docker build --rm=true --force-rm=true -t scriptsync/tts container
# tag it with ECR url (create container called "tts" in ECR first)
docker tag scriptsync/tts:latest 992382755464.dkr.ecr.us-east-1.amazonaws.com/tts:latest
# push the image
docker push 992382755464.dkr.ecr.us-east-1.amazonaws.com/tts:latest
# deploy function
aws lambda create-function --region us-east-1 --function-name tts \
--package-type Image \
--code ImageUri=992382755464.dkr.ecr.us-east-1.amazonaws.com/tts:latest \
--role arn:aws:iam::992382755464:role/transcribe-lambda-role
# update function
aws lambda update-function-code --function-name tts --image-uri 992382755464.dkr.ecr.us-east-1.amazonaws.com/tts:latest
Running dockerized AWS lambda locally
Assumes Dockerfile has CMD ["app.handler"] /
Additional info to test locally: https://aws.amazon.com/blogs/compute/a-guide-to-locally-testing-containers-with-amazon-ecs-local-endpoints-and-docker-compose/
# first run the docker image
docker run --env-file .env -p 9000:8080 --rm scriptsync/tts:latest
# then test by making a post request (path is very specific)
curl -XPOST "http://localhost:9001/2015-03-31/functions/function/invocations" -d '{"foo": "bar"}'
# to run without having to provide the path, add this nginx config
server {
server_name tts.scriptsync.app;
location / {
proxy_pass http://localhost:9000/2015-03-31/functions/function/invocations;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
}
# then invoke using
curl -XPOST "https://tts.scriptsync.app" -d '{"foo": "bar"}'
Starting a Dev-Mode Container
To run our container to support a development workflow, we will do the following:
- Mount our source code into the container
- Install all dependencies, including the "dev" dependencies
- Start nodemon to watch for filesystem changes
cd /path/to/getting-started/app
# for Unix
# `-w /app` sets container's present working directory where command will run from
# `-v "$(pwd):/app"` bind mount (link) the host's present getting-started/app directory to the container's /app directory. Docker requires absolute paths for binding mounts, so we use pwd for printing abs path of working dir
# `node:18-alpine` - the image to use (base image for app from Dockerfile)
# `sh -c "yarn install && yarn run dev"` - start shell using sh and running yarn install, then run dev
docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
node:18-alpine \
sh -c "yarn install && yarn run dev"
# to see when app is ready
docker logs -f <container-id>
# for powershell
docker run -dp 3000:3000 `
-w /app -v "$(pwd):/app" `
node:18-alpine `
sh -c "yarn install && yarn run dev"
Multi-container Apps
Put container on a network. Assign it at start or connect an existing container.
# create teh network
docker network create todo-app
# start a MySQL container and attach it to network
docker run -d \
--network todo-app --network-alias mysql \
-v todo-mysql-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=todos \
mysql:8.0
# connect to database and verify it connects / password is "secret"
docker exec -it <mysql-container-id> mysql -p
mysql> SHOW DATABASES;
# start a new container using netshoot image and connect to the same network
docker run -it --network todo-app nicolaka/netshoot
dig mysql # inside the container, run dig to verify / look up IP of the hostname mysql
# run app with mysql info
docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
--network todo-app \
-e MYSQL_HOST=mysql \
-e MYSQL_USER=root \
-e MYSQL_PASSWORD=secret \
-e MYSQL_DB=todos \
node:18-alpine \
sh -c "yarn install && yarn run dev"
TRANSCRIBE
lambda: upload mp3
trigger: api gateway - user upload function: save file to s3 return: job_id
lambda: TTS
trigger: api gateway - text/voice/service function:
- save file to s3
- transcribe lambda return:
{
mp3_signed_s3_url: "",
transcription: {}
}
lambda: on s3 file upload event - run whisper transcribe
trigger: s3 - mp3 file put (extracted mp3 or TTS) function: whisper transcribe, save transcription file to s3 return: job_id