Полезные команды Docker

Docker — это отличный инструмент для создания микросервисов, который позволяет создавать облачные приложения и системы. Самые важные сущности в Docker: образ и контейнер.

Образ — исполняемый пакет, который содержит всё необходимое для запуска приложения: код, среду выполнения, библиотеки, переменные среды и конфигурационные файлы.

Контейнер создаётся из образа. Это то, чем становится образ во время исполнения (иными словами, образом с состоянием или пользовательским процессом).

Чтобы просмотреть список запущенных контейнеров необходимо ввести команду docker ps (прямо как в Linux).

Docker — отличный инструмент для создания микросервисов, который позволяет создавать облачные приложения и системы. Чтобы выжать из него максимум через терминал, вам пригодятся 10 команд, перечисленных ниже.

  1. docker ps  — показывает список запущенных контейнеров. Некоторые из полезных флагов:
    • -a / --all — список всех контейнеров (по умолчанию показывает только запущенные);
    • -q / --quiet — перечислить только id контейнеров (полезно, когда вам нужны все контейнеры).
  2. docker pull  —  большинство образов создаётся на основе базового образа из Docker Hub. Docker Hub содержит множество готовых образов, которые можно использовать вместо того, чтобы создавать и настраивать свой собственный. Чтобы скачать определённый образ или набор образов (репозиторий), используйте команду docker pull.
  3. docker build  —  эта команда собирает образ Docker из Dockerfile и «контекста». Контекст сборки — это набор файлов, расположенных по определённому пути или URL. Используйте флаг -t, чтобы задать имя образа. Например, команда docker build -t my_container . соберёт образ, используя текущую директорию, на что указывает точка в конце.
  4. docker run  —  запускает контейнер, на основе указанного образа. Эту команду можно дополнять другими, например, docker run my_image -it bash запустит контейнер, а затем запустит в нём bash.
  5. docker logs  —  эта команда используется для просмотра логов указанного контейнера. Можно использовать флаг --follow, чтобы следить за логами работающей программы: docker logs --follow my_container.
  6. docker volume ls  —  показывает список томов, которые являются предпочитаемым механизмом для сохранения данных, генерируемых и используемых контейнерами Docker.
  7. docker rm  —  удаляет один и более контейнеров, например, docker rm my_container.
  8. docker rmi  —  удаляет один и более образов, например, docker rmi my_image.
  9. docker stop  —  останавливает один и более контейнеров. Команда docker stop my_container остановит один контейнер, а docker stop $(docker ps -a -q) — все запущенные. Более грубый способ — использовать docker kill my_container, который не пытается сначала аккуратно завершить процесс.
  10. Можно комбинировать эти команды. Например, для очистки всех контейнеров и образов:
    • Останавливаем все запущенные контейнеры docker stop $(docker ps -q).
    • Удаляем все остановленные контейнеры docker rm $(docker ps -a -q).
    • Удаляем все образы docker rmi $(docker images -q).

Весь список команд можно почитать в документации.

Запуск Hashicorp Vault в Docker Compose

docker-compose.yml

version: '3.9'

services:

  vault:
    image: vault:1.9.4
    container_name: vault
    volumes:
      - ./config:/vault/config
      - ./policies:/vault/policies
      - ./data:/vault/data
    ports:
      - 8200:8200
    environment:
      - VAULT_ADDR=http://0.0.0.0:8200
      - VAULT_API_ADDR=http://0.0.0.0:8200
      - VAULT_ADDRESS=http://0.0.0.0:8200
    cap_add:
      - IPC_LOCK
    command: vault server -config=/vault/config/vault.json
    
  vault-ui:
    image: djenriquez/vault-ui:2.3.0
    container_name: vault-ui
    ports:
      - 8000:8000
    environment:
      - 'VAULT_URL_DEFAULT=http://vault:8200'
      - VAULT_AUTH_DEFAULT=GITHUB

Файл располагается в корневом каталоге.

Файл vault.json:

{                                    
  "listener":  {                     
    "tcp":  {                        
      "address":  "0.0.0.0:8200",  
      "tls_disable":  "true"         
    }                                
  },                                 
  "backend": {                       
    "file": {                        
      "path": "/vault/file"          
    }                                
  },                                 
  "default_lease_ttl": "168h",       
  "max_lease_ttl": "0h",
  "api_addr": "http://0.0.0.0:8200"
}

Выполнить сборку контейнера и запустить можно при помощи команды:

docker-compose up --build -d

Запуск Jenkins в Docker Compose

docker-compose.yml

version: '3'
services:
  jenkins:
    image: jenkins:2.60.3
    container_name: jenkins
    # uncomment for docker in docker
    # run http://localhost:8080/restart (An error occurred during installation: No such plugin: cloudbees-folder)
    privileged: true
    user: root
    volumes:
        # enable persistent volume (warning: make sure that the local jenkins_home folder is created)
        - ./jenkins_home:/var/jenkins_home
        # mount docker sock and binary for docker in docker (only works on linux)
        - ./var/run/docker.sock:/var/run/docker.sock
        - ./usr/bin/docker:/usr/bin/docker
    ports:
      - 8113:8080

Файл располагается в корневом каталоге.

Выполнить сборку контейнера и запустить можно при помощи команды:

docker-compose up --build -d

Запуск Golang в Docker Compose

docker-compose.yml

version: '3.9'

services:

  golang:
    build: ./build
    container_name: golang
    restart: always
    # stdin_open: true # docker run -i
    tty: true        # docker run -t
    volumes:
      - ./build/source:/go/tmp/src

Файл располагается в корневом каталоге.

Dockerfile

# Базовый образ
FROM golang:1.14.4-buster
# Папка приложения
ARG APP_DIR=app
# Копирование файлов
COPY . /go/tmp/src/${APP_NAME}
# Рабочая директория
WORKDIR /go/tmp/src/${APP_NAME}
# Библиотеки
# RUN go get <путь_к_библиотеке>
# RUN go get github.com/streadway/amqp

Файл располагается в ./build

hello.go

package main

func main() {
	println("Hello, World!")
}

Файл располагается в ./ServiceGo/source

Выполнить сборку контейнера и запустить можно при помощи команды:

docker-compose up --build -d

Отформатировать файл:

docker-compose exec golang gofmt hello.go

Запустить приложение:

docker-compose exec golang go run hello.go

Запуск PostgreSQL 9 в Docker Compose

docker-compose.yml

version: '3'
services:
  postgres:
    build: ./build
    container_name: postgres
    restart: always
    volumes:
        - ./data:/var/lib/postgresql/data
    environment:
        - "POSTGRES_USER=any_user"
        - "POSTGRES_PASSWORD=any_password"
        - "POSTGRES_DB=any_dev_db"
    ports:
        - "54321:5432"

Файл располагается в корневом каталоге.

Dockerfile

FROM postgres:9.6-alpine

Файл располагается в ./build

Выполнить сборку контейнера и запустить можно при помощи команды:

docker-compose up --build -d

Запуск Elasticsearch и Kibana в Docker Compose

docker-compose.yml

version: '3.9'

services:

  elasticsearch:
    build: ./build-elasticsearch
    container_name: elasticsearch
    restart: always
    environment:
      - "discovery.type=single-node"
    ports:
      - "9200:9200"
    networks:
      - es01

  kibana:
    build: ./build-kibana
    container_name: kibana
    restart: always
    environment:
      - SERVER_NAME=kibana
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200/
    links:
      - "elasticsearch"
    ports:
      - "5601:5601"
    networks:
      - es01

networks:
  es01:

Файл располагается в корневом каталоге.

Dockerfile для Elasticsearch

FROM docker.elastic.co/elasticsearch/elasticsearch:7.8.0

Файл располагается в ./build-elasticsearch.

Dockerfile для Kibana

FROM docker.elastic.co/kibana/kibana:7.8.0

Файл располагается в ./build-kibana.

Подробнее можно почитать на официальных страницах:

Выполнить сборку контейнера и запустить можно при помощи команды:

docker-compose up --build -d

Запуск Mongo и Mongo Express в Docker Compose

docker-compose.yml

version: '3.9'

services:
  
  mongo:
    build: ./build-mongo
    container_name: mongo
    restart: always
    networks:
      - mongo
    ports:
      - "27017:27017"
    environment:
      - MONGO_INITDB_ROOT_USERNAME=${MONGO_ROOT_USER}
      - MONGO_INITDB_ROOT_PASSWORD=${MONGO_ROOT_PASSWORD}
      - MONGO_INITDB_DATABASE=test-database

  mongo-express:
    build: ./build-mongo-express
    container_name: mongo-express
    restart: always
    networks:
      - mongo
    ports:
      - "8093:8081"
    environment:
      - ME_CONFIG_MONGODB_SERVER=mongo
      - ME_CONFIG_MONGODB_PORT=27017
      - ME_CONFIG_MONGODB_ENABLE_ADMIN=true
      - ME_CONFIG_MONGODB_ADMINUSERNAME=mongo
      - ME_CONFIG_MONGODB_ADMINPASSWORD=mongo
      - ME_CONFIG_MONGODB_AUTH_DATABASE=admin
      - ME_CONFIG_MONGODB_AUTH_USERNAME=${MONGO_ROOT_USER}
      - ME_CONFIG_MONGODB_AUTH_PASSWORD=${MONGO_ROOT_PASSWORD}
      - ME_CONFIG_BASICAUTH_USERNAME=${MONGOEXPRESS_LOGIN}
      - ME_CONFIG_BASICAUTH_PASSWORD=${MONGOEXPRESS_PASSWORD}

networks:
  mongo:

Файл располагается в корневом каталоге.

Файл .env:

MONGO_ROOT_USER=mongo
MONGO_ROOT_PASSWORD=mongo
MONGOEXPRESS_LOGIN=mongo
MONGOEXPRESS_PASSWORD=mongo

Dockerfile для Mongo

FROM mongo:5.0

Файл располагается в ./build-mongo

Dockerfile для Mongo Express

FROM mongo-express:0.54

Файл располагается в ./build-mongo-express

Подробнее можно почитать на официальных страницах:

docker-compose up --build -d

Выполнить сборку контейнера и запустить можно при помощи команды:

Запуск RabbitMQ в Docker Compose

docker-compose.yml

version: '3.9'
services:
   rabbitmq:
      build: ./build
      container_name: rabbitmq
      environment:
       - RABBITMQ_ERLANG_COOKIE=SWQOKODSQALRPCLNMEQG
       - RABBITMQ_DEFAULT_USER=rabbit
       - RABBITMQ_DEFAULT_PASS=rabbit
      ports:
       - "15672:15672"
       - "5672:5672"

Файл располагается в корневом каталоге.

Dockerfile

FROM rabbitmq:3-management
COPY ./conf/enabled_plugins /etc/rabbitmq/enabled_plugins

Файл располагается в ./build

enabled_plugins

[rabbitmq_management, rabbitmq_management_visualiser].

Файл располагается в ./conf/enabled_plugins

Подробнее можно почитать на официальной странице Docker Hub — RabbitMQ.

Выполнить сборку контейнера и запустить можно при помощи команды:

docker-compose up --build -d

Введение в контейнерную виртуализацию Docker

Вы работали с виртуальными машинами? Oracle VM VirtualBox, например? VirtualBox — это гипервизорная виртуализация, т.е. вы под основной ОС запускаете несколько программных эмуляций железа, на которых крутятся произвольные «гостевые» ОС (Linux, Windows, Mac OS, FreeBSD, вообще любые другие).

Это удобно, и для некоторых задач, незаменимо, но, как вы, наверное, понимаете, не слишком производительно. Очень много ресурсов тратится на эмуляцию: накладные расходы ОС и т.п.

Существует качественно иной подход к виртуализации — контейнерная. Это когда запущенно одно ядро ОС (обычно какой-то линукс) а вокруг него крутятся множество изолированных друг от друга юзерспейсов, каждый из которых для ползователя выглядит как отдельный хост.

Минусы в том, что ты можешь запускать только ОС которые могут работать с одним и тем же ядром (например RedHat и Debian или Ubuntu). К тому же изоляция не такая абсолютная как в гипервизорной виртуализации, т.е. если один хост словил панику ядра — лежат все.

Но с другой стороны очень жирный плюс в том, что накладных расходов меньше на порядки, и уже можно говорить об эффективности такой системы.

Предполагаю, что многие хостинги работают с контейнерной виртуализацией. И когда вы оплачиваете хостинг, то вас выдают какой-то сервак из облака и есть вероятность что вам как раз дают такой контейнер который шарит ядро ОС с другими контейнерами.

Докер использует эту идею следующим образом. Вы настраиваете внутри такого виртуального хоста все необходимое окружение, наборы библиотек, скрипты, сервисы, все что угодно с любыми путями и версиями (напомню, изнутри выглядит все так, будто это отдельная машина и весь сервак ваш). Потом вся эта конфигурация сохраняется в удобный для распространения пакет который можно передавать заказчику / заказчикам, а они просто парой команд разворачивают этот контейнер на своем докере.

В итоге решается огромное количество проблем с деплоем, конфигурацией, конфликтами библиотек (одной программе нужна одна версия библиотеки, другой — другая, и без танцев с бубном такое не всегда разруливается), а из таких контейнеров программы видят только то что нужно и никаких конфликтов.

В общем, интересная штука, которая может быть полезна многим.