文章目录

  • Dockerfile的书写
  • Dockerfile常见问题
  • RUN 和CMD的区别
  • 通过Dockerfile构建应用
  • 启动应用
  • 利用Volume持久化Container数据到宿主机上(named volume)
  • 创建volume
  • 启动容器时候使用-v参数
  • volume所同步的容器数据在宿主机哪里?
  • 利用bind mounts将宿主机的数据同步至Container
  • 如何区分named volume和bind mounts?
  • Compose将多个容器整合成一个完整的应用
  • 利用docker-compose.yml将多个应用整合在一起
  • 启动
  • Docker各个命令快速查阅
  • 使用Docker Desktop可视化操作
  • 示例代码
  • 其他建议



Docker文档写的相当好,不但示例全,而且是思路很连贯下来的。基本是你顺着他的思路下来,对Docker就有了很整体的认识

Dockerfile的书写

# From后面跟镜像image名字
From node:12-alpine
# RUN 是构建镜像其中的一个步骤,这里代表拉取镜像后,在镜像中安装以下几个软件
RUN apk add --no-cache python2 g++ make
# 后续的命令的工作目录
WORKDIR /app
# 将宿主机的当前文件夹下的app文件夹拷贝至容纳的/app下
COPY ./app .
# 在当前镜像中使用yarn
RUN yarn install --production
# CMD是镜像已经构建完毕之后,启动容器之后,容器里默认执行的命令,CMD只能有一个,如果出现多个,则以最后一个生效
CMD ["node", "src/index.js"]
# 暴露的端口,只是暴露端口,但是没有和宿主机端口进行映射,要映射的话还是要通过-p参数
EXPOSE 3000

Dockerfile常见问题

RUN 和CMD的区别

其实有这个问题其实是更深层次的原因,可能是自己没搞懂Docker中Image和Container的概念

docker如何设置中文 docker中文文档_容器

  • Container可以简单理解为我们最终跑的应用,那最终的应用在机器上是什么呢?是一个进程
  • 那Image是什么呢,是为了能让我们应用跑起来的前置配置,也可以叫应用需要的环境

所以搞懂这两个,再回过头来看,就懂了。

  • RUN是针对Image配置的,简单理解为,我为了搭建好程序运行的环境,我需要的步骤都用RUN来定义
  • CMD是针对Container-进程的,CMD是进程启动之后,默认的执行的命令
  • docker如何设置中文 docker中文文档_容器_02

通过Dockerfile构建应用

docker build -t getting-started .

最后的这个点代表的是 build context,在docker build文档中搜索即可找到,还不理解就Google这个两个单词

构建过程会实时在Termial上看到,如下图

docker如何设置中文 docker中文文档_docker如何设置中文_03

我们上述的那几步都可以看到

启动应用

docker run -dp 3000:3000 getting-started

利用Volume持久化Container数据到宿主机上(named volume)

Docker中各个Container是隔离(isolation)的,即使两个Container来自于同一个Image,那么其各自的数据无法共享。同时对Container的中文件的改变,随着容器的删除会消失,也就是无法持久化

With the previous experiment, we saw that each container starts from the image definition each time it starts. While containers can create, update, and delete files, those changes are lost when the container is removed and all changes are isolated to that container. With volumes, we can change all of this.

Volumes provide the ability to connect specific filesystem paths of the container back to the host machine. If a directory in the container is mounted, changes in that directory are also seen on the host machine. If we mount that same directory across container restarts, we’d see the same files


创建volume

docker volume create todo-db

启动容器时候使用-v参数

docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started

上面的(/etc/todos)是容器里的路径,也就是volume监控容器内/etc/todos下的文件,当产生变化时,会自动将这些变化同步到宿主机的磁盘上,从而解决容器无法持久化数据的问题

Start the todo app container, but add the -v flag to specify a volume mount. We will use the named volume and mount it to /etc/todos, which will capture all files created at the path

volume所同步的容器数据在宿主机哪里?

docker volume inspect todo-db

文档

利用bind mounts将宿主机的数据同步至Container

场景之一是本地开发时,源码发生改动时可以不重新构建Container的情况下,更新Conntainer

  • named volume是将Container里的数据同步至Host中
  • bind mounts是将Host里的数据同步至Container中

In the previous chapter, we talked about and used a named volume to persist the data in our database. Named volumes are great if we simply want to store data, as we don’t have to worry about where the data is stored.

With bind mounts, we control the exact mountpoint on the host. We can use this to persist data, but it’s often used to provide additional data into containers. When working on an application, we can use a bind mount to mount our source code into the container to let it see code changes, respond, and let us see the changes right away.

如何区分named volume和bind mounts?

named volume和bind mounts都定义在volume下,如何区分呢?

  • 前面是看着像名字的是named volume,是将container数据持久化至host中。例如

todo-db:/etc/todos

  • 前面明显能看着是路径的,是bind mounts,是将host的改动同步至container中。例如

/usr/local:/usr/local

docker 也提供了mount参数,通过type区分是volume还是bind mounts,并且docker官方建议使用mount参数而不是使用-v参数。

有关docker容器中如何管理数据,以及bind mounts 和 volume 的特别详细的使用场景,见官方文档-Manage data in Docker部分

Compose将多个容器整合成一个完整的应用

In general, each container should do one thing and do it well

一个完整的企业级应用可能由前端+后端+数据库+Redis+MQ组成

那么在docker的世界里,上述的每一部分都应该放在不同的container中,并通过统一的网络来沟通

但是即使这样,还是有些复杂,即部署一个系统的时候,还是要分别部署各个container,验证、然后配置网络,有没有类似于一键部署的方式。于是docker-compose出现了

The big advantage of using Compose is you can define your application stack in a file, keep it at the root of your project repo (it’s now version controlled), and easily enable someone else to contribute to your project. Someone would only need to clone your repo and start the compose app. In fact, you might see quite a few projects on GitHub/GitLab doing exactly this now.

利用docker-compose.yml将多个应用整合在一起

# compose 的schema的版本,类似于XML文件的version
version: "3.7"

services:
  app:
    image: node:12-alpine
    # 意思是We’re starting a shell using sh (alpine doesn’t have bash) and running yarn install to install all dependencies and then running yarn run dev. If we look in the package.json, we’ll see tha#t the dev script is starting nodemon
    command: sh -c "yarn install && yarn run dev"
    # 端口映射
    ports:
      - 3000:3000
    # 容器内的工作目录
    working_dir: /app
    # 这里使用的是bind mounts,即将host的内容同步到container中
    volumes:
      - ./app:/app
    environment:
      MYSQL_HOST: mysql
      MYSQL_USER: root
      MYSQL_PASSWORD: secret
      MYSQL_DB: todos
  mysql:
    image: mysql:5.7
    # 这里是使用的是named volume,即将container中的数据持久化至host中
    volumes:
      - todo-mysql-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: todos
# 在docker-compose中不会自动根据volume创建named volume,所以这里要声明
volumes:
  todo-mysql-data:

启动

docker-compose up -d

docker如何设置中文 docker中文文档_容器_04


docker如何设置中文 docker中文文档_java_05

可以看到,根据上面的配置,docke-compose创建了两个container

  • mysql_1
  • app_1

根据配置创建了volume,还自动创建了统一的网络

Docker各个命令快速查阅

docker如何设置中文 docker中文文档_docker_06

使用Docker Desktop可视化操作

使用Docker Desktop能够很方便的让我们在本地查看docker的一些信息

docker如何设置中文 docker中文文档_docker如何设置中文_07


同时也可以直接在Docker Desktop中进入相应容器中,而无需在命令行中再去敲命令

  • 点击某个container,这里点击的是get-started_app_1
  • 点击右上角的CLI就会自动打开Terminal,填充命令进入container中,非常方便

随着Docker越来越普及,再学习使用其他软件的时候,我们可以转变思路。无需再在自己的机器上装软件,各种配置环境变量等。直接一个docker镜像拉下来,快速进入学习阶段。等学会了,直接一删镜像。把主要精力放在真正的学习上,而不是被各种软件的安装耗没了学习热情