Docker学习笔记(配置镜像加速,持续更新中)
title: Docker基础
date: 2020-03-19 10:29:51
categories: 微服务基础设施
- 虚拟机里不能装虚拟机,但可以装Docker
- 镜像和容器的关系类似于类与对象
- 容器之间独立,(隔离机制)(沙箱机制)
- docker由C/S结构组成,我们的命令去请求服务端,服务端返回请求结果
使用脚本自动安装 Docker
在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,Ubuntu 系统上可以使用这套脚本安装:
$ curl -fsSL get.docker.com -o get-docker.sh
# 可能会出现 404 错误,请移步下面的特别说明
$ sudo sh get-docker.sh --mirror Aliyun
执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker CE 的 Edge 版本安装在系统中。
2018 年 7 月 21 日,貌似阿里云这边在做调整,故导致 Docker 的 Aliyun 安装脚本不可用,是永久性还是临时性的尚不清除,如果你已经按照之前的操作安装 Docker,请按以下步骤进行修复并重新安装
- 如果已经使用了 Aliyun 脚本安装并成功的
- 请先卸载 Docker,命令为:
apt-get autoremove docker-ce
- 删除
/etc/apt/sources.list.d
目录下的docker.list
文件
- 请先卸载 Docker,命令为:
- 使用
AzureChinaCloud
镜像脚本重新安装,命令为:sudo sh get-docker.sh --mirror AzureChinaCloud
配置镜像加速器
请在 /etc/docker/daemon.json
中写入如下内容(如果文件不存在请新建该文件)(第二个位置为私服Registry)
{
"registry-mirrors": [
"https://qy5lms4s.mirror.aliyuncs.com"
],
"insecure-registries": [
"172.18.48.57:5000"
]
}
注意,一定要保证该文件符合 json 规范,否则 Docker 将不能启动。
之后重新启动服务。
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
注意:如果您之前查看旧教程,修改了
docker.service
文件内容,请去掉您添加的内容(--registry-mirror=https://registry.docker-cn.com
),这里不再赘述
Docker镜像
下载
docker pull tomcat
docker pull tomcat:9-jre8
docker pull ip:port/tomcat:9-jre8
列出本地镜像
docker images
docker image ls
- 镜像下载的是压缩体积大小
- 可以通过以下命令来便捷的查看镜像、容器、数据卷所占用的空间
docker system df
- 列出部分镜像
docker image ls ubuntu
启动
- 启动tomcat (启动一次新建一个容器)
docker run -p 8088:8080 (--name mytomcat(容器名)) tomcat:9-jre8
(将Tomcat的8080端口映射到宿主机的8088端口)
docker run -P(大写) tomcat:8-jre8 (宿主机随机端口,docker端口由EXPOSE决定)
- 启动Ubuntu (启动一次新建一个容器)
$ docker run -it --rm \
ubuntu:16.04 \
bash
[email protected]:/# cat /etc/os-release
-it:这是两个参数,一个是 -i:交互式操作,一个是 -t 终端。我们这里打算进入 bash 执行一些命令并查看返回结果,因此我们需要交互式终端。(将主线程交给Docker)
--rm:这个参数是说容器退出后随之将其删除。默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动 docker rm。我们这里只是随便执行个命令,看看结果,不需要排障和保留结果,因此使用 --rm 可以避免浪费空间。
ubuntu:16.04:这是指用 ubuntu:16.04 镜像为基础来启动容器。
bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 bash
虚悬镜像
<none> <none> 00285df0df87 5 days ago 342 MB
要删除
$ docker image prune
无互交模式时
docker rmi $(docker images -q -f dangling=true)
镜像更新
docker pull ubuntu:16.04
删除镜像
如果该镜像还有容器没有删除,先删除容器
docker image rm [选项] <镜像1> [<镜像2> ...]
docker rmi <镜像1> [<镜像2> ...]
docker image rm 4e7840b49fad
docker rmi tomcat:8-jre8
使用 DockerFile 定制镜像
DockerFile定制镜像
- 将我的应用程序打包到镜像里,然后可以到处运行
- 像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建
- 首先在 /usr/local 目录下新建一个docker 文件夹,再建一个tomcat文件夹,最后建立一个文本文件Dockerfile
Dockerfile脚本
- 一个定制tomcat的简单例子
FROM tomcat:8-jre8
WORKDIR /usr/local/tomcat/webapps/ROOT/
RUN rm -rf *
RUN echo "hello docker! hello world!" > /usr/local/tomcat/webapps/ROOT/index.html
构建定制对象
- 构建镜像
docker build -t qblog .
将当前目录打包成压缩包,传到服务端
- 镜像构建上下文(Context)
上文的构建命令表示 :把当前目录大包为上下文,传到服务端
表面上我们好像是在本机执行各种 docker
功能,但实际上,一切都是使用的远程调用形式在服务端(Docker 引擎)完成。也因为这种 C/S 设计,让我们操作远程服务器的 Docker 引擎变得轻而易举,这就引入了上下文的概念。当构建的时候,用户会指定构建镜像上下文的路径,docker build
命令得知这个路径后,会将路径下的所有内容打包,然后上传给 Docker 引擎(通过REST API),这样 Docker 引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件。
如果在 Dockerfile
中这么写:
COPY ./package.json /app/
这并不是要复制执行 docker build
命令所在的目录下的 package.json
,也不是复制 Dockerfile
所在目录下的 package.json
,而是复制 上下文(context) 目录下的 package.json
。
一般来说,应该会将 Dockerfile
置于一个空目录下,或者项目根目录下。如果该目录下没有所需文件,那么应该把所需文件复制一份过来。如果目录下有些东西确实不希望构建时传给 Docker 引擎,那么可以用 .gitignore
一样的语法写一个 .dockerignore
,该文件是用于剔除不需要作为上下文传递给 Docker 引擎的。
Dockerfile指令
-
FROM
-
指定基础镜像(在那个镜像的基础上定制)
-
FROM tomcat:8-8jre
-
-
RUN
-
用来执行命令行命令(shell格式)
-
RUN echo "hello docker!" > /usr/local/tomcat/webapps/ROOT/index.html
-
-
WORKDIR
-
用来指定工作目录,可以是Dockerfile 的命令执行目录,或者是bash的默认目录
-
WORKDIR /usr/local/tomcat/webapps/ROOT/ //再次进入容器 [email protected]:/usr/local/docker/tomcat# docker run -it --rm qblog2 bash [email protected]:/usr/local/tomcat/webapps/ROOT#
之前说过每一个
RUN
都是启动一个容器、执行命令、然后提交存储层文件变更。第一层RUN cd /app
的执行仅仅是当前进程的工作目录变更,一个内存上的变化而已,其结果不会造成任何文件变更。而到第二层的时候,启动的是一个全新的容器,跟第一层的容器更完全没关系,自然不可能继承前一层构建过程中的内存变化。因此如果需要改变以后各层的工作目录的位置,那么应该使用WORKDIR
指令。 -
-
COYP
WORKDIR /usr/local/tomcat/webapps/ROOT
COPY my-shop-web-admin-1.0.0-SNAPSHOT.zip .
-
ADD
-
可以自动解压缩 tar 包
-
更高级复制,比如
<源路径>
可以是一个URL
,这种情况下,Docker 引擎会试图去下载这个链接的文件放到<目标路径>
去。下载后的文件权限自动设置为600
,如果这并不是想要的权限,那么还需要增加额外的一层RUN
进行权限调整,另外,如果下载的是个压缩包,需要解压缩,也一样还需要额外的一层RUN
指令进行解压缩。所以不如直接使用RUN
指令,然后使用wget
或者curl
工具下载,处理权限、解压缩、然后清理无用文件更合理。因此,这个功能其实并不实用,而且不推荐使用
-
-
CMD
- 用来启动镜像里面的程序
-
ENTRYPOINT
-
ENV
-
VOLUME
-
EXPOSE
-
EXPOSE
指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是docker run -P
时,会自动随机映射EXPOSE
的端口
-
Docker 容器
列出Dockers容器及信息
docker ps -a
启动或暂停一个已存在的容器
docker start(stop) 5f7f86902b8c
删除容器和 批量删除
docker rm 2a0c11797f39
//删除所有未运行的容器
docker rm $(sudo docker ps -a -q)
//强行删掉一个容器
[email protected]:/usr/local/docker/mysql/conf# docker rm -f mysql
守护态运行
在后台运行,不占用控制台主线程
//启动第一个容器
[email protected]:/usr/local/docker/tomcat# docker run -p 8088:8080 --name swing-tomcat -d tomcat:8-jre8
f100430594dd9700ea36f6f0d03e34378f4a80923a19aacacf3e0706f8dad008
//启动第二个容器
[email protected]:/usr/local/docker/tomcat# docker run -p 8089:8080 --name swing-tomcat2 -d tomcat:8-jre8
cb851d2775fd6214237acf4429c270604418aa137cc812e66a6be2b2e053c502
以bash的方式进入容器
docker exec -it ddfa08d12284 bash
数据卷
数据卷
是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:
-
数据卷
可以在容器之间共享和重用 - 对
数据卷
的修改会立马生效 - 对
数据卷
的更新,不会影响镜像 -
数据卷
默认会一直存在,即使容器被删除
注意:
数据卷
的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的被指定为挂载点的目录中的文件会隐藏掉,能显示看的是挂载的数据卷
实例:
[email protected]:/usr/local/docker/tomcat# mkdir ROOT
[email protected]:/usr/local/docker/tomcat# cd ROOT/
[email protected]:/usr/local/docker/tomcat/ROOT# vi index.html
[email protected]:/usr/local/docker/tomcat/ROOT# docker run -p 8082:8080 --name volumetest -d \
> -v /usr/local/docker/tomcat/ROOT:/usr/local/tomcat/webapps/ROOT tomcat:8-jre8
261ab7efe7e89b77efec51b9fd2e67fc4379daa72a4b95d5fefff31c03e4d5e0
Docker构建MySQL
- MySQL 8.0 :InnoDB 支持事务 效率也提高了,支持原生分布式解决方案
docker run -p 3308:3306 --name mysql \
-v /usr/local/docker/mysql/conf:/etc/mysql \
-v /usr/local/docker/mysql/logs:/var/log/mysql \
-v /usr/local/docker/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=qqhzn.000 \
-d mysql:5.7.22
-p 3308:3306:将容器的3306端口映射到主机的3308端口
-v /usr/local/docker/mysql/conf:/etc/mysql:将主机当前目录下的 conf 挂载到容器的 /etc/mysql
-v /usr/local/docker/mysql/logs:/var/log/mysql:将主机当前目录下的 logs 目录挂载到容器的 /var/log/mysql
-v /usr/local/docker/mysql/data:/var/lib/mysql:将主机当前目录下的 data 目录挂载到容器的 /var/lib/mysql
-e MYSQL\_ROOT\_PASSWORD=123456:初始化root用户的密码
-
使用数据卷配置MySQL容器最大能导入的sql语句
- 在启动容器内配置
//首先启动一个MySQL容器 docker run -p 3308:3306 --name mysql \ -v /usr/local/docker/mysql/logs:/var/log/mysql \ -v /usr/local/docker/mysql/data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=qqhzn.000 \ -d mysql:5.7.22 //进入这个启动的容器中 [email protected]:/usr/local/docker/mysql# docker exec -it mysql bash //查询MySQL配置文件的位置 [email protected]:/# whereis mysql mysql: /usr/bin/mysql /usr/lib/mysql /etc/mysql /usr/share/mysql //查询配置 [email protected]:/# cd /etc/mysql [email protected]:/etc/mysql# cd conf.d/ [email protected]:/etc/mysql/conf.d# cat mysqldump.cnf [mysqldump] quick quote-names max_allowed_packet = 16M //将`max_allowed_packet`的配置追加到mysqld.cnf末尾中 [email protected]:/etc/mysql/mysql.conf.d# echo "max_allowed_packet = 128M" >> mysqld.cnf
- 上面配置是临时的修改,当容器销毁后,有需要重新配置,因此要将容器中的配置复制放到宿主机,作用于新容器
//将容器里的配置文件拷贝入宿主机 [email protected]:/usr/local/docker/mysql/conf# docker cp mysql:/etc/mysql . //将复制文件内的文件移动到上级目录 [email protected]:/usr/local/docker/mysql/conf/mysql# mv *.* .. [email protected]:/usr/local/docker/mysql/conf# rm -rf mysql/ //删掉原有的容器 [email protected]:/usr/local/docker/mysql/conf# docker rm -f mysql //删掉挂载的数据文件 [email protected]:/usr/local/docker/mysql# rm -rf data/ //新建数据库并挂在数据卷 [email protected]:/usr/local/docker/mysql# docker run -p 3308:3306 --name mysql \ -v /usr/local/docker/mysql/conf:/etc/mysql \ -v /usr/local/docker/mysql/logs:/var/log/mysql \ -v /usr/local/docker/mysql/data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=qqhzn.000 \ -d mysql:5.7.22
项目的容器化部署
- 先初始化数据库数据
- 再用数据卷导入已经解压的目录
[email protected]:/usr/local/docker/tomcat/ROOT# ll
total 20
drwxr-xr-x 5 root root 4096 Mar 17 17:57 ./
drwxr-xr-x 3 root root 4096 Mar 17 14:01 ../
drwxr-xr-x 2 root root 4096 Mar 17 10:05 META-INF/
drwxr-xr-x 4 root root 4096 Mar 17 10:05 static/
drwxr-xr-x 7 root root 4096 Mar 17 10:05 WEB-INF/
[email protected]:/usr/local/docker/tomcat# docker run -p 8088:8080 --name myshoptomcat -d \
> -v /usr/local/docker/tomcat/ROOT:/usr/local/tomcat/webapps/ROOT tomcat:8-jre8
- 记得修改数据源,并且要先启动MySQL再启动Tomcat
- 查看tomcat日志
docker logs myshoptomcat
//一直监听者日志的变化
docker logs -f myshoptomcat
Docker Compose
- 解决部署多个容器的复杂启动参数,和容器的管理
Compose
中有两个重要的概念:
- 服务 (
service
):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。 - 项目 (
project
):由一组关联的应用容器组成的一个完整业务单元,在docker-compose.yml
文件中定义。
Compose
的默认管理对象是项目,通过子命令对项目中的一组容器进行便捷地生命周期管理。
安装
Docker Compose 存放在Git Hub,不太稳定。你可以也通过执行下面的命令,高速安装Docker Compose。
curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.4/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
使用
docker-compose.yml
编写 docker-compose.yml
文件,这个是 Compose 使用的主模板文件。
(不能用 Tab)
caversion: '3'
services:
tomcat:
restart: always
image: tomcat:8-jre8
container_name: mytomcat
ports:
- 8088:8080
运行 compose 项目
[email protected]:/usr/local/docker/tomcat# docker-compose up
//守护态
[email protected]:/usr/local/docker/tomcat# docker-compose up -d
此时访问本地 8088
端口即可
命令说明
模板文件
docker-compose部署项目
version: '3'
services:
web:
restart: always
image: tomcat:8-jre8
container_name: myshoptomcat
ports:
- 8088:8080
volumes:
- /usr/local/docker/myshop/ROOT:/usr/local/tomcat/webapps/ROOT
mysql:
restart: always
image: mysql:5.7.22
container_name: myshopmysql
ports:
- 3308:3306
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: 123456
command:
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
--explicit_defaults_for_timestamp=true
--lower_case_table_names=1
--max_allowed_packet=128M
--sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO"
volumes:
- mysql-data:/var/lib/mysql
volumes:
mysql-data:
- 导入数据库
- 解压项目压缩包到ROOT目录下,修改数据源
- 重启docker-compose
docker-compose up
docker-compose down