Dockerfile & Docker Compose(实战总结)
Dockerfile
Dockerfile 是用来构建Docker镜像文件,是由一条条构建镜像所需的指令构成的脚本。
步骤:
- 编写Dockerfile 文件
- docker build 构建镜像
- docker run 运行镜像
- docker push 发布镜像
体系结构:
- FROM:基础镜像,当前的镜像基于哪个镜像
- MAINTAINER:镜像作者、邮箱
- WORKDIR:设置工作目录,终端默认登陆进来的工作目录
- EXPOSE:当前容器对外暴露的端口
- USER:指定镜像以什么样的用户执行,默认是root
- ENV:设置环境变量 (可以写多条),构建镜像中的环境变量
- ADD:将宿主机的文件复制到容器内,如果是一个压缩文件, 将会在复制 后自动解压
- COPY:和ADD相似,但是如果有压缩文件并不能解压
- VOLUME:容器数据卷,用于数据保存和持久化工作
- RUN:容器构建时需要运行的命令,等同于操作shell脚步,例子:RUN yum -y install vim
- CMD:指定一个容器启动时运行的命令,可以有多个CMD,但只有最后一个会生效。在构建容器时,会被 docker run 后面指定的参数覆盖。
- ENTRYPOINT:和CMD相似,但是并不会被docker run指定的参数覆盖,而是追加参数
- ONBUILD:当创建一个被继承的Dockerfile,会被触发,触发器
RUN和CMD的区别:
CMD是在docker run时运行
RUN是在docker build时运行
例子:构建JDK镜像
# 来自基础镜像
FROM centos:7
# 指定镜像创建者信息
MAINTAINER goodyan<good.qq.com>
# 切换工作目录 /usr/local
WORKDIR /usr/local
# 创建一个存放jdk的路径
RUN mkdir /usr/local/java
# 安装vim插件
RUN yum -y install vim
# 将jdk压缩包复制并解压到容器中/usr/local/java
ADD jdk-8u171-linux-x64.tar.gz /usr/local/java
# 配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_171
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH
CMD ["/bin/bash"]
构建镜像语法:
# -f 后可以省略,会生成在当前目录上
docker build -f / dockerfiel文件位置) -t 要生成的镜像名:[版本号] .
docker build -f /home/dockerdir/dockerfiel -t tomcatNew:1.0 .
# 查看是否构建成功
docker images
将本地镜像推送到阿里云镜像仓库
# 1.登录阿里云Docker Registry, 密码为开通服务时设置的密码
docker login --username=用户名 registry.cn-xxx(每个人地址不一样)
# 2.标记此镜像为阿里云仓库的镜像
docker tag [镜像id] registry.cn-xxxx.xxx.com/xxx/jdk:[镜像版本号]
# 3.提交
docker push 镜像名:[镜像版本号]
Docker网络
容器间的互联和通信以及端口映射,容器IP变了可以通过服务名直接网络通信不受影响。Docker默认提供了3种网络模式,
- bridge 默认的桥接模式,并将容器连接到一个docker0
- host 容器将不会虚拟出自己的网卡,使用宿主机的IP和端口
- container模式 这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace
- none 该Docker容器没有网卡、IP、路由等信息
基本命令:
# 查看ip
ifconfig 或者 ip addr
# 查看docker网络模式列表
docker network ls
# 创建新的网络
docker network create 网络名
# 删除的网络名
docker network rm 网络名
# 查看的网络名
docker network inspect 网络名
# 连接络名
docker network connect 网络名
# 中断络名
docker network disconnect 网络名
# 查看某个容器的网关信息(倒数20行内)
docker inspect 容器id | tail -n 20
# 查看到bridge 就是桥接模式,Gateway:网关,IPAddress:ip(注意:这里的ip,每次创建/删除容器,IP会变)
桥接模式
# 查看的bridge 网络信息,通过grep 获取名称项目(默认是docker0)
docker network inspect bridge | grep name
# 创建2个容器,后查看ip
ip addr
# 会看到多了很多veth的xxx,它们与eth0与匹配
# 我们进入某个容器内部,再查看IP
ip addr
# 会看到etho的xxx 与外面的对应,一个容器内部的etho,对应外部的veth
host 模式
# 查看的bridge 网络信息,通过grep 获取名称项目(默认是docker0)
docker network inspect host
# 它的容器里的IP和端口,与宿主机一致,创建容器的 -p 命令就会失效
自定义网络
# 可以解决,ping IP 和 ping 服务名 都可以成功
# 创建新的网络(yan_work)
docker network create yan_work
# 查看docker网络模式列表
docker network ls
# 创建2个容器
docker run -it -p 8081:8080 --network yan_work --name tom81 镜像名:标签名 /bin/bash
docker run -it -p 8082:8080 --network yan_work --name tom82 镜像名:标签名 /bin/bash
# 分别进入2个容器
docker exec -it 容器名称|容器id /bin/bash
# 分别查看ip(查看它们是否处于同一网段上)
ip addr
# 分别ping对应的ip地址,和服务名(是否ping成功,同一个网络会成功)
ping tom81
ping tom82
Docker部署
微服务打包Docker镜像
# 步骤1. 准备SpringBoot项目,进行打包
mvn package install
# 步骤2. 启动命令,进行测试是否启动成功
windows系统启动:java -jar xxx.jar
Linux系统启动:nohup java -jar xxx.jar
# 步骤3.创建dockerfiel文件,与jar包存在同一目录(vim Dockerfiel)
# Dockerfiel文件内容:
FROM java:8
MAINTAINER goodyan
# 指临时目录,在主机创建/tmp目录
VOLUME /tmp
# 将jar包添加到容器中,并重命名app.jar
ADD xxx*.jar app.jar
# 运行jar包
RUN bash -c 'touch /app.jar'
# 暴露对应的端口号
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
# 步骤4.上传服务器,构建镜像
docker build -f /home/xxx/dockerfiel文件地址(如果在当前目录可省略-f)-p 端口映射 -t 镜像名:1.0 .
# 例子:docker build -t test1:01 .
# 步骤5.查看镜像
docker images
# 步骤6.运行启动镜像
docker run -id --name=容器名 镜像名:标签名
或
docker run -d --name 容器名 -p 端口外:端口内 镜像名:标签名
IDEA集成Docker实现打包
步骤1:修改docker服务配置文件
# 修改配置文件
vim /lib/systemd/system/docker.service
# 修改内容
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
(修改ExecStart那行,并开启2375端口,0.0.0.0代表任何ip都可以访问)
# 重新加载配置文件
systemctl daemon-reload
# 重启docker
systemctl restart docker.service
# 查看端口是否开启
netstar -nlpt # 如果没有这个命令,安装插件 yum install net-tools
# 关闭防火墙 / 开发端口号的防火墙
firewall-cmd --list-ports # 查看
firewall-cmd --zone=public --add-port=2375/tcp --permanent # 设置
firewall-cmd --reload # 重启
步骤2:IDEA工具配置连接Docker
步骤3:使用 docker-maven-plugin插件 ,实现自动化部署
修改pop.xml文件
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<!--鏡像名字-->
<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
<imageTags>
<imageTag>latest</imageTag>
<!-- <imageTag>${project.version}</imageTag>-->
</imageTags>
<baseImage>java</baseImage>
<maintainer>821521880@qq.com</maintainer>
<workdir>/ROOT</workdir>
<cmd>["java", "-version"]</cmd>
<entryPoint>["java", "-jar", "${project.build.finalName}.jar"]</entryPoint>
<!--连接Docker 输入对应的IP地址 -->
<dockerHost>http://123.56.94.235:2375</dockerHost>
<!-- 这里是复制 jar 包到 docker 容器指定目录配置 -->
<resources>
<resource>
<targetPath>/ROOT</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
然后我们执行打包命令,就在Docker服务生成镜像
mvn clean package docker:build
步骤4:打包自动化,自动化部署
<!-- 当执行打包命令,就自动执行 build语句 -在pop.xml文件里添加->
<executions>
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
Docker认证命令配置
使用CA加密认证,访问Docker更加安全
- 创建ca文件夹,存放CA私钥/公钥
mkdir -p /usr/local/ca
cd /usr/local/ca/
- 生成私钥/公钥
openssl genrsa -aes256 -out ca-key.pem 4096
# Enter pass phrase for ca-key.pem:
# 执行后,需要输入2次密码,设置密码
openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
# 执行完,需要输入刚才设置的密码。
# 然后依次输入 1国家名字 cn 2省份名称 bj 3城市 bj 4组织名称 good ... 个人信息
- 生成server-key.pem文件
openssl genrsa -out server-key.pem 4096
# 执行完,/usr/local/ca 目录下会有3个文件
- CA来签署公钥
openssl req -subj "/CN=IP地址(或者域名www.goodysr.cn)" -sha256 -new -key server-key.pem -out server.csr
# 例子
openssl req -subj "/CN=121.40.176.56" -sha256 -new -key server-key.pem -out server.csr
- 配置白名单
echo subjectAltName=IP:IP地址,IP:0.0.0.0 >> extfile.cnf
# 例子
echo subjectAltName = IP:121.40.176.56,IP:0.0.0.0 >> extfile.cnf
- 将Docker使用属性设置仅用于服务器身份验证
echo extendedKeyUsage = serverAuth >> extfile.cnf
- 生成签名证书
openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \-CAcreateserial -out server-cert.pem -extfile extfile.cnf
# 执行完,要输入刚才设置的密码,输入密码
- 生成客户端的key.pem
openssl genrsa -out key.pem 4096
openssl req -subj '/CN=client' -new -key key.pem -out client.csr
- 使用密钥适合客户端身份验证
echo extendedKeyUsage = clientAuth >> extfile.cnf
# echo extendedKeyUsage = clientAuth >> extfile-client.cnf
- 生成cert.pem签名证书
openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \-CAcreateserial -out cert.pem -extfile extfile.cnf
# 输入完,要设置密码
- 删除不需要的文件
rm -v client.csr server.csr
- 修改权限,避免密钥损坏
chmod -v 0400 ca-key.pem key.pem server-key.pem
chmod -v 0444 ca.pem server-cert.pem cert.pem
- 归集服务器证书
cp server-*.pem /etc/docker/
cp ca.pem /etc/docker/
# 以上两步操作都在ca文件夹内,如果当前不在ca文件夹,需加上路径
# 把证书复制到/etc/docker/目录下
- 修改Docker配置
vim /lib/systemd/system/docker.service
# 修改内容
ExecStart=/usr/bin/dockerd --tlsverify --tlscacert=/etc/docker/ca.pem \
--tlscert=/etc/docker/server-cert.pem \
--tlskey=/etc/docker/server-key.pem \
-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
# 重新加载配置文件
systemctl daemon-reload
# 重启docker
systemctl restart docker
# 开放2375端口
/sbin/iptables -I INPUT -p tcp --dport 2376 -j ACCEPT
# 查看信息
iptables-save
# 重启Docker
service docker restart
- 将服务器生成的私钥密钥,保存到本地环境
/usr/local/ca 目录下的 ca.pem ca-key.pem cert.pem key.pem
保存到本地的 ca 目录下
Portainer图形化管理工具
官网:https://www.portainer.io/
官网:https://docs.portainer.io/v/ce-2.9/start/install/server/docker/linux
- 下载portainer镜像
docker search portainer
docker pull portainer/portainer
- 启动镜像
docker run -d -p 8000:8000 -p 9000:9000 --name portainer --restart=always --privileged=true \
-v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data \
portainer/portainer
- 开放端口号
firewall-cmd --list-ports
firewall-cmd --zone=public --add-port=9000/tcp --permanent
firewall-cmd --reload
- 访问9000地址
第一次登录需要创建用户,选择第一个(本机的Docker容器),可以查询仪表盘。Stacks :就是有几个Docker Compose、Container:有几个容器、Image:有几个镜像、Network:有哪些网络;我们可以查询容器,进行页面操作,进行启动、停止、删除容器,也可以查看日志信息、当前容器的负载情况,CPU、内存信息。
Docker Compose
高效的管理容器,它是一个用于定义和运行多容器 Docker 的应用程序工具
- 服务:一个个应用容器实例,比如服务1、服务2、mysql容器、nginx容器或者redis容器。
- 工程:由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。
安装
- 官网:https://docs.docker.com/compose/compose-file/compose-file-v3/
- 下载:https://docs.docker.com/compose/install/
# 下载方式:
# 1.下载适应版本的 Compose
sudo curl -L https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
# 肯能网络原因,如果下载失败就下载另一个地址
sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname-m` > /usr/local/bin/docker-compose
# 2.手动下载
# https://github.com/docker/compose/releases
# 下载 docker-compose-Linux-X86_64 文件,上传服务器 /usr/local/bin/ 目录下
# 重命名 docker-compose
mv docker-compose-Linux-X86_64 docker-compose
# 3.把文件方法bin目录下,配置可执行文件的系统变量,可以在任何目录下执行docker-compose命令
mv docker-compose /usr/local/bin/
# 4.修改文件权限
cd /usr/local/bin/
chmod 777 docker-compose
或
chmod +x /usr/local/bin/docker-compose
# 5.查看版本信息,看是否安装成功
docker-compose version
# 如果卸载
sudo rm /usr/local/bin/docker-compose
使用
创建容器
需要通过docker-compose.yml模板文件,定义一组相关的应用容器作为一个项目。
案例1管理一个tomcat、mysql:
version: "3" # 表示该docker-compose.yml文件使用的是Version 2 file format
services: # 为project定义服务。
test1: # 定义服务名称,随便起名
restart: always # 只要docker启动,容器就启动
image: test1:01 # 指的对应的镜像(默认官方镜像地址)
container_name: test1 # 指的对应的容器名
ports: # 端口映射
- "9010:9010"
volumes: # 数据卷的映射
- /app/test1:/data
networks: # 使用的网络,同一个网络下,可以直接使用服务名,不通过IP访问
- yan_net
depends_on: # 依赖于mysql服务
- mysql
test2:
image: test2:01
container_name: test2
ports:
- "9020:9020"
volumes:
- /app/test2:/data
networks:
- yan_net
depends_on:
- mysql
mysql:
image: mysql:8.0.32
container_name: mysql_master
environment:
MYSQL_ROOT_PASSWORD: '123456' # Mysql Root的密码
TZ: 'Asiz/Shanghai' # 指定时区
MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
MYSQL_DATABASE: 'db2024'
MYSQL_USER: 'yan'
MYSQL_PASSWORD: '123456'
ports:
- "3306:3306"
volumes:
- /docker/mysql/master/conf:/etc/mysql/conf.d
- /docker/mysql/master/logs:/var/log/mysql
- /docker/mysql/master/data:/var/lib/mysql
- /etc/localtime:/etc/localtime
networks:
- yan_net
command: --default-authentication-plugin=mysql_native_password # 解决外部无法访问
networks:
# Docker网络
yan_net:
常用命令:
# 启动(执行上面命令创建容器)
docker-compose -f 文件名.后缀(如果当前文件不再当前目录需要指定,可省略) up -d
# 登录到容器中
docker-compose exec 容器名 bash
# 停止所有容器
docker stop ${docker ps -qa}
docker-compose stop # 关闭所有容器
# 删除docker-compose文件内所有容器
docker-compose down
# 查看帮助
docker-compose -h
# 启动所有docker-compose服务
docker-compose up
# 启动所有docker-compose服务并后台运行
docker-compose up -d
# 停止并删除容器、网络、卷、镜像。
docker-compose down
# 进入容器实例内部 docker-compose exec
docker-compose exec yml里面的服务id
docker-compose.yml文件中写的服务id /bin/bash
# 展示当前docker-compose编排过的运行的所有容器
docker-compose ps
# 展示当前docker-compose编排过的容器进程
docker-compose top
# 查看容器输出日志
docker-compose logs yml里面的服务id
# 检查配置
docker-compose config
# 检查配置,有问题才有输出
docker-compose config -q
# 重启服务
docker-compose restart
# 启动服务
docker-compose start
# 停止服务
docker-compose stop
Docker容器监控
CAdvisor监控收集 + InfluxDB存储数据 + Granfana展示图表
用来监控:当前宿主机上所有容器的CPU,内存以及网络流量等数据。
使用
# 创建目录,在某目录下,创建docker-compose.yml文件
# 编写docker-compose.yml文件,
version: '3.1'
volumes:
grafana_data: {}
services:
influxdb:
image: tutum/influxdb:0.9
restart: always
environment:
- PRE_CREATE_DB=cadvisor
ports:
- "8083:8083"
- "8086:8086"
volumes:
- ./data/influxdb:/data
cadvisor:
image: google/cadvisor
links:
- influxdb:influxsrv
command: -storage_driver=influxdb -storage_driver_db=cadvisor -storage_driver_host=influxsrv:8086
restart: always
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
grafana:
user: "104"
image: grafana/grafana
user: "104"
restart: always
links:
- influxdb:influxsrv
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
environment:
- HTTP_USER=admin
- HTTP_PASS=admin
- INFLUXDB_HOST=influxsrv
- INFLUXDB_PORT=8086
- INFLUXDB_NAME=cadvisor
- INFLUXDB_USER=root
- INFLUXDB_PASS=root
# 进行启动,当前目录
docker-compose up
# 查看这3个服务是否启动
docker ps
# 验证
# 浏览cAdvisor收集服务,http://ip:8080/
# 浏览influxdb存储服务,http://ip:8083/
# 浏览grafana展现服务,http://ip:3000