Docker
Docker基本概念
镜像(image):Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
容器(container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像,可以类比于Maven仓库。
我的阿里云镜像加速器地址
https://2i5funqv.mirror.aliyuncs.com
Linux安装docker
如果之前安装过旧版本的Docker,可以使用下面命令卸载:
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine \
docker-ce
添加阿里云仓库
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
安装gcc相关
yum -y install gcc
yum -y install gcc-c++
安装yum工具
yum install -y yum-utils
更新yum缓存
yum makecache
安装docker CE
yum install docker-ce docker-ce-cli containerd.io -y
查看docker版本
docker version
查看docker运行状态
systemctl status docker
启动docker
systemctl start docker
停止docker
systemctl stop docker
docker自动启动
# docker 服务开机自启动命令
systemctl enable docker.service
# 关闭docker 服务开机自启动命令
systemctl disable docker.service
常用命令
镜像常用命令
列出本地镜
docker images
搜索仓库MySQL镜像
docker search mysql
下载Redis官方最新镜像
相当于:docker pull redis:latest
docker pull redis
单个镜像删除
相当于:docker rmi redis:latest
docker rmi redis
删除本地全部镜像
docker rmi -f $(docker images -q)
删除镜像有时候输入docker images -a有很多为none的镜像,可能为空悬镜像,删除命令如下:
docker image prune
docker rmi $(docker images -f "dangling=true" -q)
可能删除不掉,显示unable to delete 镜像Id (cannot be forced) - image has dependent child images
docker image inspect --format='{{.RepoTags}} {{.Id}} {{.Parent}}' $(docker image ls -q --filter since=镜像Id)
然后从上到下依次删除
删除未运行的容器
docker rm $(docker ps --all -q -f status=exited)
docker查看日志
显示最后一百行日志
docker logs -f --tail=100 [CONTAILER_ID]
进入容器
使用run运行进入,可以使用ctrl+d退出,直接退出终端
docker run -it [CONTAILER_ID] /bin/bash
已经运行的docker进入
docker exec -it [CONTAILER_ID] /bin/bash
上传文件至容器
docker cp 本地路径 [CONTAILER_ID]:容器路径
导出所有镜像
#!/bin/bash
docker save $(docker images --format '{{.Repository}}:{{.Tag}}') -o allinone.tar
导出单个镜像
docker save [IMAGE_ID]>docker.tar
导出单个容器
docker export [CONTAINER_ID] docker.tar
导入单个镜像
docker load < docker.tar
导入容器
docker load -i allinone.tar
导出脚本
#!/bin/bash
# 读取本地 "image:tag" 名称
IMG_NAME=`docker images | grep -v TAG | awk '{print $1":"$2}'`
# echo $IMG_NAME | awk '{gsub(/ /,"\n",$0)} {print $0}'
# 定义镜像存放目录
DIR="/data/docker/image_tar"
if [ ! -d "$DIR" ]; then
echo -e "${DIR} 不存在"
mkdir -p "$DIR"
echo -e "${DIR} 已创建"
else
echo -e "${DIR} 已存在"
fi
echo ""
for IMAGE in $IMG_NAME
do
echo -e "正在保存 ${IMAGE}"
SAVE_NAME=`echo $IMAGE | awk -F: '{print $1"_"$2}' | sed 's/\//_/g'`
docker save $IMAGE -o ${DIR}/${SAVE_NAME}.tar
echo -e "已保存到 ${DIR}/${SAVE_NAME}.tar"
echo ""
done
导入脚本
#!/bin/bash
# 在此处填写镜像文件的保存目录
IMAGE_DIR="/data/docker/image_tar"
for IMAGE in `ls $IMAGE_DIR`
do
echo -e "正在导入镜像 $IMAGE"
docker load -i ${IMAGE_DIR}/${IMAGE}
echo -e "已成功导入镜像 $IMAGE"
echo ""
done
容器相关命令
https://www.cnblogs.com/eden-libinglin/p/13803729.html
新建并启动容器
- -i 以交互模式运行容器;
- -t 为容器重新分配一个伪输入终端;
- –name 为容器指定一个名称;
- -p 宿主机的端口映射到容器的端口;
- -v 容器数据卷(作用:数据持久化)的使用,将容器上的指定目录挂载到宿主机的目录,从而可以实现数据的同步(删除容器并不会删除其挂载的数据卷)
docker run -i -t --name mycentos -p 9090:8080 -v /home:/usr/local
- -d 已守护方式启动容器
docker run -d mycentos #后台启动容器
docker ps # 列出正在运行的容器
docker ps -a #列出所有容器(包括未运行的)
docker start redis # 启动已经被停止的容器redis
docker restart redis # 重启容器redis
docker top redis # 列出redis容器中运行进程
docker logs rabbitmq #查看redis容器日志,默认参数
docker run -it centos /bin/bash #使用run方式在创建时进入
exit #关闭容器并退出
docker attach centos #直接进入centos容器启动命令的终端,不会启动新进程
docker exec -it centos /bin/bash #在centos容器中打开新的交互模式终端,可以启动新进程
docker inspect redis #获取镜像redis的元信息
docker stop redis #停止一个运行中的容器
docker kill redis #杀掉一个运行中的容器
docker rm -f redis #删除一个容器
docker cp rabbitmq:/[container_path] [local_path] #将rabbitmq容器中的文件copy至本地路径
容器数据卷
docker有一个问题,就是将容器删除的话,数据就会丢失。但我们需要数据的持久化,要将数据存储到本地。容器之间可以有一个数据共享的技术,Docker容器中产生的数据,同步到本地。这就是卷技术,目录的挂载,将我们容器内的目录,挂载到Linux上面。
使用如上:docker run 后面加 -v aaa:bbb 表示指定卷挂载的目录,aaa表示宿主机目录,bbb表示容器目录,这种方式为指定路径挂载。当然还有如下两种挂载方式:
具名挂载和匿名挂载
三种挂载: 匿名挂载、具名挂载、指定路径挂载
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载 docker volume ls 是查看不到的
通过 docker volume ls 命令可以查看所有卷名。所有的docker容器内的卷,没有指定目录的情况下都是在宿主机 /var/lib/docker/volumes/xxxx/_data 目录下。
Dockerfile的编写
构建步骤:
- 编写一个dockerfile文件
- docker build 构建一个镜像
- docker run 运行镜像
- docker push 发布镜像(DockerHub、阿里云从仓库等)
Dockerfile 基础知识
1、每个指令都必须是大写字母;
2、执行顺序从上到下;
3、#表示注释;
4、每一个指令都会提交一个新的镜像层,并提交。
DockerFile常用指令
FROM # 基础镜像,一切从这里开始构建
MAINTAINER # 镜像是谁写的, 姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 拷贝文件(支持正则表达式)到镜像,并自动解压(如果是压缩包)
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 保留端口配置
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代。
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
COPY # 类似ADD,将我们文件拷贝到镜像中
ENV # 构建的时候设置环境变量!
例如:springboot的dockerFile例子
FROM java:8
EXPOSE 8081
MAINTAINER chengli/931209494@qq.com
VOLUME /tmp
ARG JAR_FILE
COPY target/${JAR_FILE} /app.jar
ENTRYPOINT ["./run.sh", "restart"]
docker-compose.yml运行docker
docker-compose.yml文件内容
version: "3"
services:
manager:
build:
context: .
dockerfile: Dockerfile
# 镜像名称
image: manager-ui
ports:
- 3334:80
restart: always
# 容器名称
container_name: "manager-ui"
复制相关的文件,如果是前端,则拷贝
- default.conf(nginx配置文件)
- docker-compose.yml
- Dockerfile(docker文件)
- build(文件夹,npm run build的产物)
执行命令
docker-compose up --force-recreate --build -d
MAVEN推送Docker
先停用docker
docker stop [CONTAINER_ID]
删除停止运行的 docker
docker rm [CONTAINER_ID]
删除镜像
docker rmi [IMAGE_ID]
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.13</version>
<configuration>
<repository>${project.artifactId}</repository>
<tag>${project.version}</tag>
<buildArgs>
<JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
<!--使用docker-maven-plugin插件-->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.2.0</version>
<!--将插件绑定在某个phase执行-->
<executions>
<execution>
<id>build-image</id>
<!--用户只需执行mvn package ,就会自动执行mvn docker:build-->
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<!--覆盖相同标签镜像-->
<forceTags>true</forceTags>
<!--指定生成的镜像名-->
<imageName>${project.artifactId}</imageName>
<!-- 容器启动执行的命令,相当于dockerFile的ENTRYPOINT -->
<baseImage>openjdk:8</baseImage>
<entryPoint>["java","-jar","/${project.build.finalName}.jar"]</entryPoint>
<exposes>
<expose>8081</expose>
</exposes>
<maintainer>chengli/931209494@qq.com</maintainer>
<volumes>
<volume>/tmp</volume>
</volumes>
<!-- 指定 Dockerfile 路径-->
<!--<dockerDirectory>${project.basedir}</dockerDirectory>-->
<!--指定远程 docker api地址-->
<dockerHost>http://192.168.124.12:2375</dockerHost>
<buildArgs>
<JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
<!-- 这里是复制 jar 包到 docker 容器指定目录配置 -->
<resources>
<resource>
<targetPath>/</targetPath>
<!--jar 包所在的路径 此处配置的 即对应 target 目录-->
<directory>${project.build.directory}</directory>
<!-- 需要包含的 jar包 ,这里对应的是 Dockerfile中添加的文件名 -->
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
package之后再去docker环境中执行
docker run -d -p 8081:8081 --name [取得别名] --restart always [IMAGE_ID]