Files
rikako-note/docker/docker guide.md

9.3 KiB
Raw Blame History

docker guide

Push image to docker hub

  1. 通过命令docker login -u ${username}登录docker hub
  2. 使用docker tag命令给镜像getting-started一个新的名称。需要用docker hub id替换YOUR-USER-NAME
    $  docker tag getting-started YOUR-USER-NAME/getting-started
    
  3. 如果git push操作未指定tagname那么默认会使用tag latest
    $ docker push YOUR-USER-NAME/getting-started
    

volume mount

在一个容器中对文件进行的操作(修改、删除、新增)在容器被删除后都会丢失,即使两个容器从同一镜像启动,一个容器的修改对另一个容器仍然不可见。
volume提供了将容器中文件系统指定路径连接到宿主机的功能。在容器中被挂载的目录下,对文件的修改也会同步到宿主机的路径下。如果在不同的容器启动时挂载相同的目录,那么目录下的文件将会在容器之间进行共享。
volume可以看作是一个不透明的数据桶volume完全由docker管理docker会管理volume在磁盘中存储的位置。用户只需要指定volume的name即可。

  1. 创建docker volume
     docker volume create todo-db
    
  2. 通过--mount选项将volume挂载到容器中。使用示例如下所示
    <!--
         src指定volume的name
         target指定挂载路径
     -->
    # docker run -dp 3000:3000 --mount type=volume,src=todo-db,target=/etc/todos getting-started
    

volume detail

如果想要知道volume的详细信息例如在宿主机中的存储位置可以调用docker volume inspect命令:

$ docker volume inspect todo-db
[
    {
        "CreatedAt": "2019-09-26T02:18:36Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
        "Name": "todo-db",
        "Options": {},
        "Scope": "local"
    }
]

bind mount

相对于volume mountbind mount能够让同一目录在宿主机和容器之间进行共享宿主机对于路径下文件的修改能对容器可见。

  1. 执行如下命令创建bind mount将宿主机路径挂载到容器中
    <!-- 
         当mount type为bind时
         src为宿主机路径
         target为容器的目标路径
     -->
    docker run -it --mount type=bind,src="$(pwd)",target=/src ubuntu bash
    

bind mount和volume mount区别

对于bind mount不管宿主机中是否由内容宿主机路径对应的文件内容都会覆盖容器目录中的内容。
对于volume mount如果volume中没有内容会将容器目录下的内容复制到宿主机的volume中如果volume中有内容volume中内容会覆盖容器目录中的内容。

docker run -v

docker run -v命令后由三部分组成,形式为src:dest:mode当src为宿主机的一个路径时使用的是bind mount如果src为一个name时使用的是volume mount。第三块是可选的为读写权限默认情况下mode为rw。

multi container app

通常情况下每个容器之应该做一件事情。故而例如一个应用需要mysql应该将mysql置于另一个容器中进行部署。

container networking

容器在默认情况下是隔离运行的,不知道位于同一机器上的其他容器和进程。故而,容器之间通过网络进行通信。
如果多个容器需要通过network进行通信那么需要将多个容器放置到同一个network中。

create network

可以通过如下命令创建一个网络:

$ docker network create todo-app

如下命令会启动一个mysql容器并且将其添加到todo-app的网络中

$ 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

--network todo-app选项会将mysql容器添加到todo-app网络中,而--network-alias mysql则会创建一条dns mysql该条dns指向mysql容器的ip地址。

在上述指令中,并没有调用docker volume create命令来创建volumedocker知道我们要使用命名好的volume并会为我们自动创建。

nicolaka/netshoot

nicolaka/netshoot容器中集成了很多网络工具在解决网络问题时会很有用。

  1. 将netshoot容器添加到指定网络中
    $  docker run -it --network todo-app nicolaka/netshoot
    
  2. 在netshoot容器中使用dig命令dig是很有用的DNS工具
    $ dig mysql
    
    dig命令输出如下
     ; <<>> DiG 9.18.8 <<>> mysql
     ;; global options: +cmd
     ;; Got answer:
     ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32162
     ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
    
     ;; QUESTION SECTION:
     ;mysql.				IN	A
    
     ;; ANSWER SECTION:
     mysql.			600	IN	A	172.23.0.2
    
     ;; Query time: 0 msec
     ;; SERVER: 127.0.0.11#53(127.0.0.11)
     ;; WHEN: Tue Oct 01 23:47:24 UTC 2019
     ;; MSG SIZE  rcvd: 44
    
    其中ANSWER SECTION输出了network-alias mysql对应的ip地址。

    mysql并不是一个有效的域名但是docker能将该network-alias解析为对应容器的ip地址

docker compose

docker compose是用于定义和共享多容器应用的工具。通过compose可以通过一个yaml文件来定义应用服务并且通过单行命令启动和停止多容器应用服务。

创建compose file

  1. 定义container的service条目和对应image我们可以为service指定任何名称。该指定的名称会自动成为network-alias
    services:
        app:
            image: node:18-alpine
    
  2. 在为service定义name和image之后可以为service指定command
    services:
        app:
            image: node:18-alpine
            command: sh -c "yarn install && yarn run dev"
    
  3. 为service指定ports
    services:
        app:
            image: node:18-alpine
            command: sh -c "yarn install && yarn run dev"
            ports:
            - 3000:3000
    
  4. 为service设置workdir或挂载卷时通过如下方式进行
    services:
        app:
            image: node:18-alpine
            command: sh -c "yarn install && yarn run dev"
            ports:
                - 3000:3000
            working_dir: /app
            volumes:
                - ./:/app
    
  5. 如果需要为service指定环境变量如果如下方式进行配置
    services:
        app:
            image: node:18-alpine
            command: sh -c "yarn install && yarn run dev"
            ports:
                - 3000:3000
            working_dir: /app
            volumes:
                - ./:/app
            environment:
                MYSQL_HOST: mysql
                MYSQL_USER: root
                MYSQL_PASSWORD: secret
                MYSQL_DB: todos
    
  6. 在docker run时通过-v选项指定的volume name不存在那么volume会自动被创建但是在compose file中通过volumes指定的volume name并不会被自动创建。想要创建volume必须yml文件的顶层volumes:中指定volume 。
    通常情况下,只用指定volume-name:即可,会使用默认的选项。
    示例如下所示:
    services:
        app:
            # The app service definition
        mysql:
            image: mysql:8.0
            volumes:
                - todo-mysql-data:/var/lib/mysql
    
        volumes:
            todo-mysql-data:
    
  7. 最终整合两个docker container的应用yml文件配置如下所示
    services:
    app:
        image: node:18-alpine
        command: sh -c "yarn install && yarn run dev"
        ports:
        - 3000:3000
        working_dir: /app
        volumes:
        - ./:/app
        environment:
        MYSQL_HOST: mysql
        MYSQL_USER: root
        MYSQL_PASSWORD: secret
        MYSQL_DB: todos
    
    mysql:
        image: mysql:8.0
        volumes:
        - todo-mysql-data:/var/lib/mysql
        environment:
        MYSQL_ROOT_PASSWORD: secret
        MYSQL_DATABASE: todos
    
    volumes:
    todo-mysql-data:
    

run application stack

可以通过docker compose up命令来启动application stack。可以通过添加-d选项在后台运行

 docker compose up -d

默认情况下docker compose会自动为compose文件中的application stack创建一个network。 如果想要停止application stack可以调用docker compose down命令。

默认情况下docker compose down并不会移除创建的volume如果想要移除volume可以指定选项--volumes