Dockerfile & Docker Swarm & Docker Stack & Docker Compose

Dockerfile

通俗地讲,它是为了指导单个镜像从无到有的构建过程。如果你镜像是从Docker registry上面拉下来的,那就用不到这个文件;如果你是自己的应用,想打包成镜像,那就需要这个文件。

Dockerfile资料:http://www.docker.org.cn/dockerppt/114.html

Docker Swarm

一句话,这个东西是用来搭建Docker集群的。

示例:(两台已经安装好Docker的机器:192.168.192.128 和 192.168.192.130

128上:(初始化为Manager,然后开启防火墙端口)

[root@localhost DockerComposeFolder]# docker swarm init
Swarm initialized: current node (pmio659q4pm90nlvtoe5ak293) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-17usxu5fddmp2laagvpatbgrq8tiigfj4ejgcmuof1oy942842-9r9jkrf33tico042cs684e886 192.168.192.128:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

[root@localhost DockerComposeFolder]# firewall-cmd --zone=public --add-port=2377/tcp --permanent
success
[root@localhost DockerComposeFolder]# systemctl restart firewalld

130上:(加入集群成为一个Worker)

[root@localhost admin]# firewall-cmd --zone=public --add-port=2377/tcp --permanent
success
[root@localhost admin]# systemctl restart firewalld
[root@localhost admin]# docker swarm join --token SWMTKN-1-17usxu5fddmp2laagvpatbgrq8tiigfj4ejgcmuof1oy942842-9r9jkrf33tico042cs684e886 192.168.192.128:2377
This node joined a swarm as a worker.

128上:(列出节点列表)

[root@localhost DockerComposeFolder]# docker node ls
ID                            HOSTNAME                STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
ply3z1rbyxn967zqdqltc5j7w     localhost.localdomain   Ready               Active                                  19.03.2
pmio659q4pm90nlvtoe5ak293 *   localhost.localdomain   Ready               Active              Leader              19.03.1

当前节点退出集群

docker swarm leave --force

更新集群

docker swarm update

应用示例:(在Learder上【128节点】

1. 编写一个compose文件

[root@localhost DockerComposeFolder]# vim docker-compose-demo.yml

---

version: '3.7'

services:
  redis:
    image: redis
    ports:
      - "6379"
    deploy:
      replicas: 2
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure
    networks:
      - swarmnet

  visualizer:
    image: dockersamples/visualizer:stable
    ports:
      - "8080:8080"
    stop_grace_period: 1m30s
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      placement:
        constraints: [node.role == manager]
    networks:
      - swarmnet
networks: # 自定义网络
  swarmnet:

2. 启动

[root@localhost DockerComposeFolder]# docker stack deploy -c docker-compose-demo.yml my_first_app
Creating network my_first_app_swarmnet
Creating service my_first_app_visualizer
Creating service my_first_app_redis
[root@localhost DockerComposeFolder]# 

3. 查看

# stack列表
[root@localhost DockerComposeFolder]# docker stack ls
NAME                SERVICES            ORCHESTRATOR
my_first_app        2                   Swarm

# 服务列表
[root@localhost DockerComposeFolder]# docker service ls
ID                  NAME                      MODE                REPLICAS            IMAGE                             PORTS
w3a6mgfouljz        my_first_app_redis        replicated          2/2                 redis:latest                      *:30005->6379/tcp
pmakz6gwandv        my_first_app_visualizer   replicated          1/1                 dockersamples/visualizer:stable   *:8080->8080/tcp

4. 访问Visualizer(Leader的IP:8080)记得开放防火墙端口

5. 停止stack

[root@localhost DockerComposeFolder]# docker stack rm my_first_app
Removing service my_first_app_redis
Removing service my_first_app_visualizer
Removing network my_first_app_swarmnet

6. 说明配置:deploy下的placement

配置这个可以规定服务的位置,如上面的结果,Visualizer只会在Manager上运行,而redis则会出现在Manager以及Worker上。

部署应用示例

打包镜像参考:https://www.cnblogs.com/LUA123/p/11436805.html

注意,本示例中,web程序的开放端口是8081

1. 配置仓库

因为我们的本地应用仓库在128上,如果130节点也想运行我们的web项目,那么需要配置仓库地址,不然找不到

vim /etc/docker/daemon.json
# 里面是仓库地址,根据情况自行修改
{
  "insecure-registries":["192.168.192.128:443"]
}

2. 编写yml文件

version: '3.7'

services:
  web:
    image: 192.168.192.128:443/hello-2
    deploy:
      replicas: 2
      restart_policy:
        condition: on-failure
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
    ports:
      - "8081:8081"
    networks:
      - swarmnet

  redis:
    image: redis
    ports:
      - "6379"
    deploy:
      replicas: 2
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure
    networks:
      - swarmnet

  visualizer:
    image: dockersamples/visualizer:stable
    ports:
      - "8080:8080"
    stop_grace_period: 1m30s
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      placement:
        constraints: [node.role == manager]
    networks:
      - swarmnet
networks: # 自定义网络
  swarmnet:

启动

[root@localhost DockerComposeFolder]# docker stack deploy -c docker-compose-demo.yml my_first_app
Creating network my_first_app_swarmnet
Creating service my_first_app_redis
Creating service my_first_app_visualizer
Creating service my_first_app_web

128节点查看

130节点查看

访问128节点的Visualizer :http://192.168.192.128:8080/

打开8081防火墙端口后访问

Docker Stack(Docker堆栈)

在上面的小例子已经有了体现。一句话,能够一键部署一整套服务。

1. docker stack deploy 部署新的堆栈或者更新现有堆栈

docker stack deploy -c docker-compose-demo.yml my_first_app

-c:指定配置文件
my_first_app:指定stack名字

2. docker stack ls 显示堆栈列表

[root@localhost DockerComposeFolder]# docker stack ls
NAME                SERVICES            ORCHESTRATOR
my_first_app        2                   Swarm

3. docker stack ps 列出堆栈中的任务

[root@localhost DockerComposeFolder]# docker stack ps my_first_app
ID                  NAME                        IMAGE                             NODE                    DESIRED STATE       CURRENT STATE           ERROR               PORTS
r41ww3p604z5        my_first_app_visualizer.1   dockersamples/visualizer:stable   localhost.localdomain   Running             Running 8 minutes ago                       
1jirtqlappdp        my_first_app_redis.1        redis:latest                      localhost.localdomain   Running             Running 8 minutes ago                       
yr4sz7k5uwpk        my_first_app_redis.2        redis:latest                      localhost.localdomain   Running             Running 8 minutes ago                       

4. docker stack services 列出堆栈中的服务

[root@localhost DockerComposeFolder]# docker stack services my_first_app
ID                  NAME                      MODE                REPLICAS            IMAGE                             PORTS
pmakz6gwandv        my_first_app_visualizer   replicated          1/1                 dockersamples/visualizer:stable   *:8080->8080/tcp
w3a6mgfouljz        my_first_app_redis        replicated          2/2                 redis:latest                      *:30005->6379/tcp

5. docker stack rm 删除一个或多个堆栈

[root@localhost DockerComposeFolder]# docker stack rm my_first_app
Removing service my_first_app_redis
Removing service my_first_app_visualizer
Removing network my_first_app_swarmnet

Docker Compose

它是为了指导单个“服务”的构建过程,“服务”实际上包含一个或者多个运行状态下的容器。在服务中运行的单个容器称为任务,每个任务的ID是数字唯一递增的。一般你的应用都需要依赖很多其它的环境,比如:数据库啊、redis啊、zookeeper啊等等,你也可以一个一个配置参数启动,但是有了docker-compose,你只需要把事先准备的好的配置写在文件里,然后docker-compose up一键启动即可,相比一个一个手动启动,方便了很多也减少了出错机会。你会发现,它和Docker Stack的作用差不多。区别如下:

stack部署到集群(配合swarm),compose只能部署到一个节点。

stack会跳过build过程,所以stack只能使用现成的镜像;compose不会跳过build,所以compose对开发人员比较友好。

虽然compose也能进行生产环境的部署,但是在集群角度来看,stack更适合生产部署。

详解docker-compose.yml文件

version

查看Docker信息执行:docker info 或者 docker --version

[root@localhost admin]# docker --version
Docker version 19.03.1, build 74b1e89

提醒:你可以结合docker 命令(比如:build、run、network等等)来理解docker-compose

Run命令:https://docs.docker.com/engine/reference/commandline/run/

Docker-Compose-File:https://docs.docker.com/compose/compose-file/

以下选项是 docker-compose up 支持,而docker stack deploy 不支持的

build
cgroup_parent
container_name
devices
tmpfs
external_links
links
network_mode
restart
security_opt
sysctls
userns_mode

compose文件(包含大部分选项)

version: "3.7"
services:
  webapp:
    # build,构建一个镜像(利用docker-compose执行此文件);如果在集群模式下部署,将忽略此项,docker stack仅仅接受预先构建好的镜像。
    build:
      # 包含Dockerfile的路径,当提供的是相对路径,解释为相对于compose文件的位置。
      context: ./dir
      # Compose使用指定的Dockerfile文件来构建
      dockerfile: Dockerfile-alternate
      # 构建参数,这些参数只能在构建过程中访问
      args:
        - buildno=1
        - hash=cdc3b19
      # 缓存(v3.2开始)
      cache_from:
        - alpine:latest
      # 构建指定阶段的Dockerfile(v3.4开始。参考:多阶段构建文档:https://docs.docker.com/develop/develop-images/multistage-build/)
      target: prod
      # 指定生成的容器中/dev/shm分区的大小(v3.5开始。可以为字符串'1gb'或者整数数字1000000)
      shm_size: '1gb'

    # build或者指定镜像的话,此项为镜像名称
    image:app:tag
    # 容器标签(也可以这样写 com.example.description: "Accounting webapp")
    labels:
      - "com.example.description=Accounting webapp"
    # 添加容器功能(执行man 7 capabilities查看全部)
    cap_add:
      - ALL
    # 删除容器功能
    cap_drop:
      - NET_ADMIN
      - SYS_ADMIN
    # 为容器指定可选的父cgroup
    cgroup_parent: m-executor-abcd
    #覆盖默认命令(也可以是个列表,类似于Dockerfile:command: ["bundle", "exec", "thin", "-p", "3000"])
    command: bundle exec thin -p 3000
    # 默认docker-compose up 会按照顺序启动服务,如果你有前后顺序,可以指定这个参数,代表db和redis先于webapp启动
    depends_on:
      - db
      - redis
    # 部署(仅限v3版本,并且只适合集群部署(docker stack),docker-compose up 将忽略这个选项)
    deploy:
      # 启动容器副本数
      replicas: 6
      # 资源限制
      resources:
        # 不超过单核CPU的50%可用处理时间 & 不超过50M内存
        limits:
          cpus: '0.50'
          memory: 50M
        # 始终可用25%CPU时间 & 20M内存
        reservations:
          cpus: '0.25'
          memory: 20M
      # 重启策略
      restart_policy:
        # 重启时机(none、on-failure、any,默认any)
        condition: on-failure
        # 重启尝试的等待时间
        delay: 5s
        # 最大重试次数(默认永远重试)
        max_attempts: 3
        # 在决定重新启动是否成功之前等待多长时间(默认立即决定)
        window: 120s
      # 配置服务如何更新
      update_config:
        # 一次更新的容器数
        parallelism: 2
        # 更新一组容器之间的等待时间
        delay: 10s
      # 服务标签
      labels:
        com.example.description: "This label will appear on the web service"
    # 覆盖默认的entrypoint
    entrypoint: /code/entrypoint.sh
    # 从文件添加环境变量。可以是单个值(env_file: .env)或列表,文件内容每一行都是var=val格式化的,# 开头的和空行都被忽略
    env_file:
      - ./common.env
      - ./apps/web.env
      - /opt/secrets.env
    # 添加环境变量,如果是布尔值要用引号括起来
    environment:
      - RACK_ENV=development
      - SHOW=true
      - SESSION_SECRET
    # 暴露端口但是不把它们发布到主机,它们只能被链接服务访问。只能指定内部端口。
    expose:
      - "3000"
      - "8000"
    # 链接到外部的容器(格式为 容器名称:别名)
    external_links:
      - redis_1
      - project_db_1:mysql
      - project_db_1:postgresql
    # 添加主机名映射
    extra_hosts:
      - "somehost:162.242.195.82"
      - "otherhost:50.31.209.229"
    # 日志
    logging:
      # 驱动(默认json-file,还可以为syslog和none)
      driver: "json-file"
      options:
        # 日志最大大小,以及文件数量
        max-size: "200k"
        max-file: "10"
    # 网络(要引入顶级配置的network)
    networks:
     - some-network
     - other-network
    # 暴露端口,以HOST:CONTAINER格式映射端口
    ports:
      - "3000"
      - "3000-3005"
      - "8000:8000"
      - "9090-9091:8080-8081"
      - "49100:22"
      - "127.0.0.1:8001:8001"
    # 重启("no",always,on-failure,unless-stopped)
    restart: "no"
    # 设置内核参数
    sysctls:
      - net.core.somaxconn=1024
      - net.ipv4.tcp_syncookies=0
    # 将容器目录映射到主机目录(格式 HOST:CONTAINER)
    volumes:
      - "/var/run/postgres/postgres.sock:/var/run/postgres/postgres.sock"
      - "dbdata:/var/lib/postgresql/data"

  redis:
    image: redis
  db:
    image: postgres

# 配置网络
networks:
  some-network:
  other-network:
    external:
      name: actual-name-of-network

命令

Usage:
  docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
  docker-compose -h|--help

Options:
  -f, --file FILE             Specify an alternate compose file
                              (default: docker-compose.yml)
  -p, --project-name NAME     Specify an alternate project name
                              (default: directory name)
  --verbose                   Show more output
  --log-level LEVEL           Set log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
  --no-ansi                   Do not print ANSI control characters
  -v, --version               Print version and exit
  -H, --host HOST             Daemon socket to connect to

  --tls                       Use TLS; implied by --tlsverify
  --tlscacert CA_PATH         Trust certs signed only by this CA
  --tlscert CLIENT_CERT_PATH  Path to TLS certificate file
  --tlskey TLS_KEY_PATH       Path to TLS key file
  --tlsverify                 Use TLS and verify the remote
  --skip-hostname-check       Don't check the daemon's hostname against the
                              name specified in the client certificate
  --project-directory PATH    Specify an alternate working directory
                              (default: the path of the Compose file)
  --compatibility             If set, Compose will attempt to convert keys
                              in v3 files to their non-Swarm equivalent

Commands:
  build              Build or rebuild services
  bundle             Generate a Docker bundle from the Compose file
  config             Validate and view the Compose file
  create             Create services
  down               Stop and remove containers, networks, images, and volumes
  events             Receive real time events from containers
  exec               Execute a command in a running container
  help               Get help on a command
  images             List images
  kill               Kill containers
  logs               View output from containers
  pause              Pause services
  port               Print the public port for a port binding
  ps                 List containers
  pull               Pull service images
  push               Push service images
  restart            Restart services
  rm                 Remove stopped containers
  run                Run a one-off command
  scale              Set number of containers for a service
  start              Start services
  stop               Stop services
  top                Display the running processes
  unpause            Unpause services
  up                 Create and start containers
  version            Show the Docker-Compose version information

例:docker-compose-simple.yml

version: '3.7'
services:
  zookeeper:
    image: zookeeper
    ports:
      - "2181:2181"

1. docker-compose up 创建并启动服务

# 指定yml文件,后台启动服务
[root@localhost DockerComposeFolder]# docker-compose -f docker-compose-simple.yml up -d
Creating network "dockercomposefolder_default" with the default driver
Creating dockercomposefolder_zookeeper_1 ... done

2. docker-compose stop 停止服务

[root@localhost DockerComposeFolder]# docker-compose -f docker-compose-simple.yml stop
Stopping dockercomposefolder_zookeeper_1 ... done

3. docker-compose start 启动已存在的服务

[root@localhost DockerComposeFolder]# docker-compose -f docker-compose-simple.yml start
Starting zookeeper ... done

4. docker-compose restart 重启服务

[root@localhost DockerComposeFolder]# docker-compose -f docker-compose-simple.yml restart
Restarting dockercomposefolder_zookeeper_1 ... done

5. docker-compose images 列出镜像

[root@localhost DockerComposeFolder]# docker-compose -f docker-compose-simple.yml images
           Container              Repository    Tag       Image Id      Size 
-----------------------------------------------------------------------------
dockercomposefolder_zookeeper_1   zookeeper    latest   e7c648f28c78   215 MB

6. docker-compose logs 查看日志

[root@localhost DockerComposeFolder]# docker-compose -f docker-compose-simple.yml logs
Attaching to dockercomposefolder_zookeeper_1
zookeeper_1  | ZooKeeper JMX enabled by default
zookeeper_1  | Using config: /conf/zoo.cfg
zookeeper_1  | 2019-10-09 06:46:29,917 [myid:] - INFO  [main:QuorumPeerConfig@133] - Reading configuration from: /conf/zoo.cfg
zookeeper_1  | 2019-10-09 06:46:29,920 [myid:] - INFO  [main:QuorumPeerConfig@375] - clientPort is not set
zookeeper_1  | 2019-10-09 06:46:29,920 [myid:] - INFO  [main:QuorumPeerConfig@389] - secureClientPort is not set
zookeeper_1  | 2019-10-09 06:46:29,929 [myid:] - ERROR [main:QuorumPeerConfig@645] - Invalid configuration, only one server specified (ignoring)
zookeeper_1  | 2019-10-09 06:46:29,932 [myid:1] - INFO  [main:DatadirCleanupManager@78] - autopurge.snapRetainCount set to 3
zookeeper_1  | 2019-10-09 06:46:29,933 [myid:1] - INFO  [main:DatadirCleanupManager@79] - autopurge.purgeInterval set to 0

7. docker-compose top 查看进程

8. docker-compose ps 查看容器

[root@localhost DockerComposeFolder]# docker-compose -f docker-compose-simple.yml ps
             Name                            Command               State                          Ports                        
-------------------------------------------------------------------------------------------------------------------------------
dockercomposefolder_zookeeper_1   /docker-entrypoint.sh zkSe ...   Up      0.0.0.0:2181->2181/tcp, 2888/tcp, 3888/tcp, 8080/tcp

9. docker-compose version 查看版本

[root@localhost DockerComposeFolder]# docker-compose -f docker-compose-simple.yml version
docker-compose version 1.24.1, build 4667896b
docker-py version: 3.7.3
CPython version: 3.6.8
OpenSSL version: OpenSSL 1.1.0j  20 Nov 2018

10. docker-compose pause 暂停服务

[root@localhost DockerComposeFolder]# docker-compose -f docker-compose-simple.yml pause
Pausing dockercomposefolder_zookeeper_1 ... done

11. docker-compose unpause 终止暂停服务

[root@localhost DockerComposeFolder]# docker-compose -f docker-compose-simple.yml unpause
Unpausing dockercomposefolder_zookeeper_1 ... done

12. docker-compose config 查看配置

[root@localhost DockerComposeFolder]# docker-compose -f docker-compose-simple.yml config
services:
  zookeeper:
    image: zookeeper
    ports:
    - published: 2181
      target: 2181
version: '3.7'

13. docker-compose port 查看服务暴露的端口

# 服务名称为我们定义在yml文件中的名字,端口为容器内部端口
[root@localhost DockerComposeFolder]# docker-compose -f docker-compose-simple.yml port zookeeper 2181
0.0.0.0:2181

14. docker-compose down 停止并移除已启动的容器

[root@localhost DockerComposeFolder]# docker-compose -f docker-compose-simple.yml down
Stopping dockercomposefolder_zookeeper_1 ... done
Removing dockercomposefolder_zookeeper_1 ... done
Removing network dockercomposefolder_default

15. docker-compose rm 移除已停止的容器

[root@localhost DockerComposeFolder]# docker-compose -f docker-compose-simple.yml rm
Going to remove dockercomposefolder_zookeeper_1
Are you sure? [yN] y
Removing dockercomposefolder_zookeeper_1 ... done

后记:若是去理解这几个东西,很好理解,但是如何灵活运用,就需要积累了(说实话官方给的文档比较节省笔墨,有很多地方看了N遍也不明所以,还是自己要多去实践)

原文地址:https://www.cnblogs.com/LUA123/p/11453308.html