Docker 101

Posted by 江湖迈杰的博客 on July 27, 2019

声明:我已委托「维权骑士」(rightknights.com)为我的文章进行维权行动。

Docker印象

为什么我们需要docker?

作为一款PaaS或者SaaS的产品,Docker利用容器技术帮助开发人员实现应用的快速构建、分发和部署。你可以得到如下好处:

  1. 实现不同应用间的运行环境隔离:Docker支持存储、系统、网络等多个方面的隔离,不同应用可以拥有独立的运行环境,运行时不会互相影响。例如在下图中,Web-server和Web service client-program均依赖库libjson和gcc,但是他们使用的版本可能存在差异,如果他们在运行宿主环境下运行时可能会导致其中一方或者双方运行失败。 通过docker技术,我们将不同的应用程序部署在不同的容器中,从而避免不同的应用程序对依赖的版本要求的冲突。

  2. 确保运行环境的可移植性:通常的,一个应用程序往往会依赖操作系统的底层接口,这就导致了同一个应用程序无法直接运行在各个操作系统(Windows、MacOS、Linux)中。由于这些操作系统的底层实现和用户接口大不相同,开发人员往往需要针对不同的系统进行开发适配,以支持对应系统平台上的程序运行(例如JVM)。如果你可以在Windows的Docker环境下运行你的程序(或者镜像,image),那么可以直接在Mac、Linux运行这个程序。

  3. 确保系统运行的安全性:得力于Docker的容器隔离技术,应用程序在运行过程中直接接触到容器内部的资源,不能访问容器以外的资源(除非开放相关访问权限),确保了宿主机资源的安全性,避免了由于程序内置的业务错误、系统漏洞导致的系统崩溃、资产损失。

  4. 应用分发的快速和一致性:利用Docker中的容器技术,我们可以将程序代码、运行环境中的依赖打包构建成docker 容器(container),通过网络分发出去,实现应用快速部署、容量动态调整。

镜像(Image)与容器(Container)

镜像是一个可执行的文件,它包括了运行程序所需的一切,包括对应的运行时、库、环境变量以及配置文件;镜像是只读不可写的。而容器是一个镜像的运行实例,往往通过镜像启动得到。

Docker实战

Docker常用的命令

命令 含义
docker run [-d] 启动容器 ,-d表示后台运行
docker image ls 列举镜像
docker container ls 查看当前运行所有的容器
docker rm 移除一个容器
docker rmi 移除一个镜像
docker ps 列举容器
docker exec 在容器中执行相关命令

docker中容器相关的命令和容器状态的转移关系如下:

Docker与MySQL

这里,我们以MySQL为例,介绍下如何利用Docker搭建本地可以访问的mysql服务。

  1. 拉取mysql官方docker镜像docker pull mysql/mysql-server:tag,其中tag可选,官方提供的tag包括5.55.65.78.0,  latest,未指定为latest。这里,我们指定为8.0
  2. 后台启动mysql-server容器,通过--name指定容器名称为mysql-db-serverdocker run --name=mysql-db-server -d mysql/mysql-server:8.0

    在进行数据库操作以前,我们需要将数据库的初始化密码修改成我们自己的密码。由于容器mysql-db-server是后台启动的,mysql的初始化密码打印在日志中,通过docker log查看相关系统日志。 这里,我们还可以通过Docker环境变量MYSQL_ROOT_PASSWORDMYSQL_USERMYSQL_PASSWORDMYSQL_DATABASE 指定对应的启动时默认的管理员、新建用户的用户名及密码、以及新建数据库的数据库名称。例如:

    docker run --name=mysql-db-server \
      -e MYSQL_ROOT_PASSWORD=root \
      -e MYSQL_USER=app \
      -e MYSQL_PASSWORD=password \
      -e MYSQL_DATABASE=test \
      mysql/mysql-server
    
  3. 将数据库的数据从容器中转移到宿主机上:在启动参数上添加--mount type=bind,src=</path-on-host-machine/datadir>,dst=/var/lib/mysql,将本地目录挂在mysql的数据库目录下即可。注意:数据库文件目录datadir需要使用绝对路径。
    docker run --name=mysql-db-server \
      -e MYSQL_ROOT_PASSWORD=root \
      -e MYSQL_USER=app \
      -e MYSQL_PASSWORD=password \
      -e MYSQL_DATABASE=test \
     --mount type=bind,src=/Users/mijack/Workshop/Dockers/mysql-db/data,dst=/var/lib/mysql \
      mysql/mysql-server
    
  4. 从外部网络访问:对于当前容器,我们无法直接从本地shell访问mysql-db-server,因为docker将容器的网络环境和本地的网络做了隔离。这里,我们希望可以通过本地直接mysql服务器,可以通过-p <hostPort>:<containerPort>指定对外暴露的端口。
    docker run --name=mysql-db-server \
      -e MYSQL_ROOT_PASSWORD=root \
      -e MYSQL_USER=app \
      -e MYSQL_PASSWORD=password \
      -e MYSQL_DATABASE=test \
     --mount type=bind,src=/Users/mijack/Workshop/Dockers/mysql-db/data,dst=/var/lib/mysql \
      -p 3306:3306 \
      mysql/mysql-server
    

    参考资料

  5. Docker实战
  6. What can I use Docker for?
  7. Deploying MySQL on Linux with Docker