Skip to content

Instantly share code, notes, and snippets.

@Raidus
Forked from bahmutov/Docker shell commands.sh
Last active March 17, 2019 14:43
Show Gist options
  • Save Raidus/4a5e0bfd329aa484a828ad898d951291 to your computer and use it in GitHub Desktop.
Save Raidus/4a5e0bfd329aa484a828ad898d951291 to your computer and use it in GitHub Desktop.
A personal cheat sheet for running local Node project in a Docker container
# See list of docker virtual machines on the local box
$ docker-machine ls
NAME ACTIVE URL STATE URL SWARM DOCKER ERRORS
default * virtualbox Running tcp://192.168.99.100:2376 v1.9.1
# Note the host URL 192.168.99.100 - it will be used later!
# Build an image from current folder under given image name
$ docker build -t gleb/demo-app .
# see list of build images
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
gleb/demo-app latest 506bf31537d4 17 minutes ago 904.5 MB
node 5.0 c4f955829812 10 weeks ago 642.2 MB
# Note both the original Node:5 and the built images are there
# Let us run the image under name 'demo'
$ docker run --name demo -p 5000:1337 -d gleb/demo-app
9f9f3ae62038805504c3c23cce4e9229008ba6bd9ea16b560a7a9e1cfa932e57
# A good security practice is to run the Docker image (if possible) in read-only mode
# by adding --read-only flag
# See "Docker security" talk at mark 22:00 https://www.youtube.com/watch?v=oANurUSaOFs
# Run docker image with a folder from HOST machine mounted
$ docker run -v /usr/source:/destination --name demo -d gleb/demo-app
# inside the container /destination folder will be pointing at /usr/source from the HOST
# Note: you can pass environment variable values to the `docker run` command
# docker run -e USER=name
# or, if the USER is already an environment var
# docker run -e USER
# or put all env variables into a file and pass its name
# docker run --env-file=<filename>
# You can check all the options passed into the running container
# docker inspect demo
# It prints the long container ID, but we can use our name "demo"
# We also mapped outside port 5000 to container's exposed port 1337
# Let us see running containers
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9f9f3ae62038 gleb/demo-app "node server.js" About a minute ago Up About a minute 0.0.0.0:5000->1337/tcp demo
# Let us make a dummy request to the app running inside the container
# We will use the virtual machine's IP and outside port 5000
$ curl 192.168.99.100:5000
Not Found
# Let us see the app's console log to confirm that it has received our request
$ docker logs demo
listening on port 1337 { subdomainOffset: 2, proxy: false, env: 'development' }
started server
<-- GET /
--> GET / 404 6ms -
# you can follow the logs along using -f (--follow) option
# Jump into the running container to run any commands
# -i option means bind STDIO from the current shell
docker exec -it demo bash
root@9f9f3ae62038:/usr/src/demo-server# ls
... list of files
root@9f9f3ae62038:/usr/src/demo-server# exit
# If you want to quickly list files in the docker container (default folder)
# you can use `docker exec`
$ docker exec -t demo ls
# ... list of files in /usr/src folder
# We can even copy files from the container back into our system
docker cp demo:/usr/src/demo-server/file.txt file.txt
# look at file.txt locally
# Running Docker container in terminal
# If you want to see the output / enter commands *inside the container* right from the terminal
# just skip -d option (-d is for detached mode)
$ docker run --name demo -it gleb/demo-app
# if the container stops (like the command terminates due to error)
# a nice trick is to run the container with dummy infinite command
# then shell into the container and find the problem
$ docker run --name demo -d gleb/demo-app tail -f /dev/null
$ docker exec -it demo bash
# Clean up containers, images, volumes, and networks all in one command.
$ docker system prune
# Custom clean up
$ docker ps --filter "status=exited" | grep 'weeks ago' | awk '{print $1}' | xargs --no-run-if-empty docker rm
# Nice!
# To stop the running container
$ docker stop demo

PG bench in docker

docker exec -it my-postgres-container bash
pgbench -U superuser -i -p 5432 -d mydb
pgbench -c 10

Tune Postgres Performance (1)

https://blog.codeship.com/tuning-postgresql-with-pgbench/

docker exec -it my-postgres-container bash
sed -i -e"s/^shared_buffers =.*$/shared_buffers = 8GB/" /var/lib/postgresql/data/postgresql.conf

Tune Postgres Performance (2)

Copy configuration from https://pgtune.leopard.in.ua/#/

docker exec -it my-postgres-container bash
psql -U superuser -c "ALTER SYSTEM SET max_connections = '200';"
...
psql -U superuser -c "SELECT pg_reload_conf();"
psql -U superuser -c "SELECT * FROM pg_settings"

Tune Postgres Performance (2)

Copy configuration from https://pgtune.leopard.in.ua/#/

docker cp my-postgres-container:/var/lib/postgresql/data/postgresql.conf .
nano postgresql.conf
...
docker cp postgresql.conf my-postgres-container:/var/lib/postgresql/data/postgresql.conf
# simple docker file
# assumes located in the same folder as the application itself
# start with node 5 base image
FROM node:5.0
# run as non-root user inside the docker container
# see https://vimeo.com/171803492 at 17:20 mark
RUN groupadd -r nodejs && useradd -m -r -g nodejs nodejs
# now run as new user nodejs from group nodejs
USER nodejs
# Create an app directory (in the Docker container)
RUN mkdir -p /usr/src/demo-server
WORKDIR /usr/src/demo-server
# Copy .npm settings and package.json into container
COPY package.json /usr/src/demo-server
COPY .npmrc /usr/src/demo-server
# and install dependencies
RUN npm install
# Copy our source into container
COPY src /usr/src/demo-server/src
COPY server.js /usr/src/demo-server
# If our server uses 1337 by default
# expose it from Docker container
EXPOSE 1337
# Finally start the container command
CMD ["node", "server.js"]
FROM postgres:9.4
ENV TERM=xterm
RUN apt-get update
RUN apt-get install -y nano
ADD scripts /scripts
# ADD scripts/setup-my-schema.sh /docker-entrypoint-initdb.d/
# Allow connections from anywhere.
RUN sed -i -e"s/^#listen_addresses =.*$/listen_addresses = '*'/" /var/lib/postgresql/data/postgresql.conf
RUN echo "host all all 0.0.0.0/0 md5" >> /var/lib/postgresql/data/pg_hba.conf
# Configure logs
RUN sed -i -e"s/^#logging_collector = off.*$/logging_collector = on/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_directory = 'pg_log'.*$/log_directory = '\/var\/log\/postgresql'/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_filename = 'postgresql-\%Y-\%m-\%d_\%H\%M\%S.log'.*$/log_filename = 'postgresql_\%a.log'/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_file_mode = 0600.*$/log_file_mode = 0644/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_truncate_on_rotation = off.*$/log_truncate_on_rotation = on/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_rotation_age = 1d.*$/log_rotation_age = 1d/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_min_duration_statement = -1.*$/log_min_duration_statement = 0/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_checkpoints = off.*$/log_checkpoints = on/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_connections = off.*$/log_connections = on/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_disconnections = off.*$/log_disconnections = on/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^log_line_prefix = '\%t \[\%p-\%l\] \%q\%u@\%d '.*$/log_line_prefix = '\%t \[\%p\]: \[\%l-1\] user=\%u,db=\%d'/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_lock_waits = off.*$/log_lock_waits = on/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_temp_files = -1.*$/log_temp_files = 0/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#statement_timeout = 0.*$/statement_timeout = 1800000 # in milliseconds, 0 is disabled (current 30min)/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^lc_messages = 'en_US.UTF-8'.*$/lc_messages = 'C'/" /var/lib/postgresql/data/postgresql.conf
# Performance Tuning
RUN sed -i -e"s/^max_connections = 100.*$/max_connections = 1000/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^shared_buffers =.*$/shared_buffers = 16GB/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#effective_cache_size = 128MB.*$/effective_cache_size = 48GB/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#work_mem = 1MB.*$/work_mem = 16MB/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#maintenance_work_mem = 16MB.*$/maintenance_work_mem = 2GB/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#checkpoint_segments = .*$/checkpoint_segments = 32/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#checkpoint_completion_target = 0.5.*$/checkpoint_completion_target = 0.7/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#wal_buffers =.*$/wal_buffers = 16MB/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#default_statistics_target = 100.*$/default_statistics_target = 100/" /var/lib/postgresql/data/postgresql.conf
VOLUME ["/var/lib/postgresql/data", "/var/log/postgresql"]
CMD ["postgres"]

Tips & tricks

Setup an alias to start Node container and map the current folder for quick isolated Linux environment. Add to ~/.alias file

# Creates Node container with mapped current folder and runs Bash shell
alias node-box='docker run -v $PWD:/src -w /src -u node -it node /bin/bash'

Additional information

Troubleshooting

If you open a new terminal, you need the Docker environment variables again. You can set them up in the current shell by running (assuming the name default for the Docker machine)

eval "$(docker-machine env default)"

If the Docker machine becomes unresponsive with status UNKNOWN when running docker-machine ls try rebuilding it

$ docker-machine rm -y default && docker-machine create -d virtualbox default && eval $(docker-machine env)

To delete all running containers and images (use -f option to force)

#!/bin/bash
# Delete all containers
docker rm $(docker ps -a -q)
# Delete all unused images
docker rmi $(docker images --filter dangling=true)
# Delete all images
docker rmi $(docker images -q)

To stop all running containers

IDS=$(docker ps -q)
docker stop $IDS
# or as a single command
docker stop $(docker ps -q)

If you have a container "demo" and would like to investigate it, start it in the interactive mode with a "bash" as entry

docker run -it --entrypoint bash demo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment