docker 入门
docker容器
镜像是只读的,基于镜像启动一个容器,这个容器才是可写的
1、docker安装
rm -fr /etc/yum.repos.d/local.repo
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo
sed -i 's#download.docker.com#mirrors.tuna.tsinghua.edu.cn/docker-ce#g' /etc/yum.repos.d/docker-ce.repo
yum install docker-ce -y
2、docker的主要组成部分
-
docker是传统的CS架构分为docker client和docker server,和mysql一样
[root@docker01 ~]# docker version Client: Version: 18.09.6 API version: 1.39 Go version: go1.10.8 Git commit: 481bc77156 Built: Sat May 4 02:34:58 2019 OS/Arch: linux/amd64 Experimental: false Server: Docker Engine - Community Engine: Version: 18.09.6 API version: 1.39 (minimum version 1.12) Go version: go1.10.8 Git commit: 481bc77 Built: Sat May 4 02:02:43 2019 OS/Arch: linux/amd64 Experimental: false
如果做监控的话,主要使用:docker info
docker主要组件有:镜像、容器、仓库, 网络,存储
启动容器必须需要一个镜像,仓库中只存储镜像:容器---镜像---仓库
3、启动第一个容器
##配置docker镜像加速
vi /etc/docker/daemon.json
{
"registry-mirrors": ["https://registry.docker-cn.com"]
}
docker run -d -p 80:80 nginx
run (创建并运行一个容器)
-d 放在后台
-p 端口映射
nginx docker镜像的名字
4、docker的镜像管理
-
搜索镜像
docker search 镜像名 选镜像的建议: 1,优先考虑官方 2,stars数量多
-
获取镜像
docker pull(push) 镜像加速器: 阿里云加速器,daocloud加速器,中科大加速器,Docker 中国官方镜像加速:https://registry.docker-cn.com 官方pull docker pull centos:6.8(没有指定版本,默认会下载最新版) 私有仓库pull docker pull daocloud.io/huangzhichong/alpine-cn:latest ##配置docker镜像加速 vi /etc/docker/daemon.json { "registry-mirrors": ["https://registry.docker-cn.com"] }
-
管理镜像
查看镜像列表 docker images ## 等价于:docker image ls 删除镜像 docker rmi 例子:docker image rm centos:latest 导出镜像 docker save 例子:docker image save centos > docker-centos7.4.tar.gz 导入镜像 docker load 例子:docker image load -i docker-centos7.4.tar.gz
5、docker的容器管理
docker run -d -p 80:80 nginx:latest
run(创建并运行一个容器)
-d 放在后台
-p 端口映射
-v 源地址(宿主机):目标地址(容器)
nginx : docker镜像的名字
docker run -it --name centos6 centos:6.9 /bin/bash
-it 分配交互式的终端
--name 指定容器的名字
/bin/bash覆盖容器的初始命令
-
容器管理
创建并运行容器 docker run image_name docker run -it image_name CMD ## docker run == docker create + docker start 停止容器 docker stop CONTAINER_ID 启动容器 docker start CONTAINER_ID 杀死容器 docker kill container_name 查看容器列表 docker ps : 列出正在运行的容器 docker ps –a : 列出所有容器 docker ps -a -l : 查看最后一个创建的容器 docker ps -a --no-trunc : 查看容器的详细信息 docker ps -a -q : 只显示容器的id 查看容器日志 docker logs CONTAINER_ID 进入容器(目的,调试,排错) *** docker exec (会分配一个新的终端tty) docker exec [OPTIONS] CONTAINER COMMAND [ARG...] docker exec -it 容器id或容器名字 /bin/bash(/bin/sh) docker attach(使用同一个终端) docker attach [OPTIONS] CONTAINER 删除容器 docker rm 批量删除容器 docker rm -f `docker ps -a -q` 总结:(*********) docker容器内的第一个进程(初始命令)必须一直处于前台运行的状态(必须夯住),否则这个容器,就会处于 退出状态! 业务在容器中运行:夯住,启动服务
6、docker容器的网络访问(端口映射)
如果不做端口映射,外网无法直接访问容器上的服务
指定映射(docker 会自动添加一条iptables规则来实现端口映射)
-p hostPort:containerPort
-p ip:hostPort:containerPort # 多个容器都想使用80端口
-p ip::containerPort # (随机端口)
-p hostPort:containerPort:udp # 使用udp开启端口映射
-p 81:80 –p 443:443 # 可以指定多个-p
eg:
docker run -d -p 80:80 nginx # 将宿主机的80端口映射到容器的80端口
docker run -d -p 10.0.0.51:80:80 nginx # 将宿主机10.0.0.51的80端口映射到容器的80 端口
docker run -d -p 10.0.0.100::53 nginx # 将宿主机的10.0.0.100分配的随机端口映射到容器的80
随机映射
docker run -P (随机端口)
还可以通过iptables来实现的端口映射
ps:
查看随机端口的分配范围:(内核参数)
sysctl -a|grep net.ipv4|grep 'range'
7、docker的数据卷管理
-v (volume):将宿主机的某个目录挂载的容器
/usr/share/nginx/html # nginx默认站点目录
-v /opt/xiaoniao:/usr/share/nginx/html
持久化
数据卷(文件或目录)
-v 卷名:/data
-v src(宿主机的目录):dst(容器的目录)
当src不是一个路径,只是一个名词,则docker会给该容器创建一个卷,可以用 docker volume ls 查看卷
docker volume ls # 列出所有卷
docker volume inspect 卷名 # 查看该卷的详细信息,里面有该卷的挂载点
小练习:
基于nginx启动一个容器,监听80和81,访问80,出现nginx默认欢迎首页,访问81,出现我们自定义的html文件。
提示: -p 80:80 -p 81:81 -v xxx:xxx -v xxx:xxxx
基于nginx多端口的多站点:
方法一:需要进入容器
1、创建并运行一个容器,如下:
docker run -it -p 80:80 -p 81:81 -v /opt/dailyfresh/:/data nginx:latest /bin/bash
2、进入容器配置nginx,/etc/nginx/ ,查看nginx收集站点的配置,即include配置。如下:
include /etc/nginx/conf.d/*.conf; #表示nginx的所有站点配置都在该路径下,并且都是以.conf结尾
3、在/etc/nginx/conf.d/目录下默认有个default.conf文件,该文件就是nginx的默认欢迎信息配置文件,期中默认监听端口是80。我们需要新建一个.conf文件,将监听端口改为81,root为站点目录,修改为我们自定义的/data目录。
4、启动nginx
直接在命令行输入 nginx
方法二:无需进入容器
1、直接在宿主机的挂载目录下生成nginx站点配置文件
echo 'server {
listen 81;
server_name localhost;
location / {
root /data;
index index.html index.htm;
}
}' > /opt/dailyfresh.conf
2、创建容器:
docker run -d -p 80:80 -p81:81 -v /opt/dailyfresh:/data -v /opt/dailyfresh.conf:/etc/nginx/conf.d/dailyfresh.conf nginx:latest /bin/bash
8、手动将容器保存为镜像
做一个基础镜像:
以一个支持ssh登录的镜像为例
1、启动一个基础容器
docker run -it centso:6
ps:
linux最小的发行版:alpine,后期如果觉得centos镜像太大,可以使用alpine代替,alpine:一个超小的linux系统
安装软件工具:
centos:yum
alpine:apk
2、在容器中安装服务
安装openssh-server包,sshd服务在openssh-server中
yum install openssh-server -y
# 查看一个服务属于哪个包:(eg: sshd服务)
yum provides sshd
3、启动服务
1、service sshd start
# 该服务启动后会在 /ect/ssh/ 下生成三个密钥对(key,pub),如下:
[root@2734cc65d85d /]# ll /etc/ssh/
total 152
-rw------- 1 root root 125811 Apr 9 14:32 moduli
-rw------- 1 root root 672 Jun 15 06:38 ssh_host_dsa_key
-rw-r--r-- 1 root root 590 Jun 15 06:38 ssh_host_dsa_key.pub
-rw------- 1 root root 963 Jun 15 06:38 ssh_host_key
-rw-r--r-- 1 root root 627 Jun 15 06:38 ssh_host_key.pub
-rw------- 1 root root 1675 Jun 15 06:38 ssh_host_rsa_key
-rw-r--r-- 1 root root 382 Jun 15 06:38 ssh_host_rsa_key.pub
-rw------- 1 root root 3879 Apr 9 14:32 sshd_config
该密钥对就是为了支持ssh登录,如果将这三个密钥对删除,则无法进行ssh登录
2、手动创建root密码
由于该容器使用的是纯净版的centos6,使得系统没有root密码,我们需要手动创建一个root密码
echo '123'|passwd --stdin root
# 这是就可以使用ssh连接容器了,eg:ssh root@172.17.0.2
4、把已经安装好服务的容器,提交为镜像
1、退出容器但不关闭当前容器
Ctrl+P+Q
2、提交为镜像
docker container commit 2734cc65d85d centos6_ssh:v1
3、查看当前镜像中是否有2中提交的镜像
docker images
5、测试镜像的功能
1、使用该镜像创建一个容器
docker run -d -p 1022:22 centos6_ssh:v1 /usr/sbin/sshd -D
# 这里的端口映射不能是用 22:22 ,因为宿主机的22端口已被占用
2、在本地通过ssh访问容器
ssh root@10.0.0.51 1022
做一个多服务镜像
手动制作一个支持ssh+nginx的镜像
1、启动一个基础容器
docker run -it -p 80:80 -p 1024:22 centos6_ssh:v1 /bin/bash
# 由于使用的是之前提交的新镜像来创建容器,这样就不用再安装ssh服务了
ps:每次启动一个docker容器,系统会覆盖三个文件,都会将宿主机的三个文件挂载到该容器上
/dev/sda3 on /etc/resolv.conf type xfs (rw,relatime,attr2,inode64,noquota) #dns,使容器能上网
/dev/sda3 on /etc/hostname type xfs (rw,relatime,attr2,inode64,noquota) # 主机名
/dev/sda3 on /etc/hosts type xfs (rw,relatime,attr2,inode64,noquota) # 将主机名解析为容器IP地址
2、安装服务
yum install nginx -y
3、将这2个服务的启动写成一个脚本
问:为什么要有这一步?
答:由于我们制作的是多服务的镜像,那么当我们使用制作好的镜像进行创建容器时,我们需要将这2个服务都给启动, 但是创建容器命令的最后一个参数,只能指定一条命令,如:
docker run -d -p 1022:22 centos6_ssh:v1 /usr/sbin/sshd -D
这样的话我们就只能启动其中一个服务,另一个服务则无法访问。那么我们只能通过一条命令将2个服务都给启动,所 以,最好的方法就是在容器提交成镜像前,在容器中写一个脚本
## 如果依赖的镜像没有设置root密码,则我们还需要手动创建root密码:
echo '123'|password --stdin root
-
编写启动多服务的脚本
该脚本中需要启动的服务,最后一个服务需要被夯住,前面的服务不能被夯住,否则从被夯住服务起,后面的服务都将无法启动。
或者使用万能方法:所有服务都正常启动,在最后一行加上:tail -f [日志路径] # 日志路径可选
vi /init.sh
#!/bin/bash service sshd restart nginx -g 'daemon off;'
4、提交为镜像
1、退出容器但不关闭当前容器
Ctrl+P+Q
2、提交为镜像 (不管容器时在运行中,还是已经挂了,只要容器没有被删除就可以提交为镜像)
docker container commit cb0761b79a73 centos6_ssh_nginx:v2
3、查看当前镜像中是否有2中提交的镜像
docker images
5、测试镜像功能
1、使用该镜像创建一个容器
docker run -d -p 1025:22 -p 81:80 centos6_ssh_nginx:v2 /bin/bash /init.sh
# 为什么使用/bin/bash 启动脚本,因为我们在创建完脚本后没有给脚本执行权限,所以使用/bin/bash 启动脚本
自定义容器镜像的密码
-
修改启动服务的脚本
vi /init.sh # 该脚本表示,如果不设置密码,则使用默认密码 123456
#!/bin/bash if [ -z $SSH_PWD ];then SSH_PWD=123456 fi echo "$SSH_PWD"|passwd --stdin root service sshd restart nginx -g 'daemon off;'
-
创建容器时,加上环境变量参数
docker run -d -p 1025:22 -p 81:80 -e "SSH_PWD=1q2w3e4r"centos6_ssh_nginx:v2 /bin/bash /init.sh -e 是 --env的简写,二者都表示environment,环境变脸 ## 环境变量就是执行:env ,后里面所有的参数,如下: [root@docker01 ~]# env | grep SSH SSH_CLIENT=10.0.0.1 2831 22 SSH_TTY=/dev/pts/0 SSH_CONNECTION=10.0.0.1 2831 10.0.0.51 22 这里只显示了过滤后的环境变量,我们可以通过export 和 unset 来添加或删除环境变量 申明环境变量: export SSH_PWD=123456 查看环境变量: [root@docker01 ~]# env | grep SSH SSH_CLIENT=10.0.0.1 2831 22 SSH_TTY=/dev/pts/0 SSH_PWD=123456 # 新增的环境变量 SSH_CONNECTION=10.0.0.1 2831 10.0.0.51 22 取消环境变量: unset SSH_PWD 查看环境变量: [root@docker01 ~]# env | grep SSH SSH_CLIENT=10.0.0.1 2831 22 SSH_TTY=/dev/pts/0 SSH_CONNECTION=10.0.0.1 2831 10.0.0.51 22 ### 新增的SSH_PWD已经被删除了
9、dockerfile自动构建docker镜像
- 我们可以通过创建dockerfile文件来自动创建docker镜像
- dockerfile 支持自定义容器的初始命令
dockerfile主要组成部分:
基础镜像信息 FROM centos:6.9
制作镜像操作指令 RUN yum install openssh-server -y
容器启动时执行指令 CMD ["/bin/bash"]
dockerfile常用指令:
FROM 这个镜像的妈妈是谁?(指定基础镜像)
MAINTAINER 告诉别人,谁负责养它?(指定维护者信息,可以没有) # 一般不用,不重要无需关注
LABLE 描述,标签 # 一般不用,不重要无需关注
RUN 你想让它干啥(在命令前面加上RUN即可)
ADD 将宿主机上的某个文件copy到dockerfile(会自动解压tar),制作docker基础的系统镜像
WORKDIR 设置当前工作目录,进入容器的当前目录(默认目录是根目录)
eg:
WORKDIR /opt # 这样,进入容器后的当前路径就是/opt/
VOLUME 给它一个存放行李的地方(设置卷,挂载主机目录) # 一般不用,不重要无需关注
EXPOSE 它要打开的门是啥(指定对外的端口)(-P 随机端口)
当我们使用自己构建的镜像运行容器时,-P 就无法指定随机端口,这时我们可以在dockerfile中加入EXPOSE来为我 们的容器来指定随机端口,以下是dockerfile中配置EXPOSE的使用示例:
EXPOSE 22 80 # 表示给容器的22和80端口随机分配映射端口
CMD 指定容器的初始命令(指定容器启动后的要干的事情)(容易被替换)
dockerfile 的其他指令:
COPY 复制文件(不会解压)rootfs.tar.gz
ENV 环境变量
示例:
ENV SSH_PWD 123456 # 创建环境变量SSH_PWD,并给其赋值 123456
当我们运行容器没有指定密码时,默认密码就是环境变量中的密码
当我们使用 -e 指定了密码,则会将环境变量SSH_PWD的值替换为
ENTRYPOINT 容器启动后执行的命令(无法被替换,启容器的时候指定的命令,会被当成参数)
当我们运行容器(docker run)时,指定了初始命令,则dockerfile中CMD 指定的初始命令会被覆盖
但,如果我们在dockerfile中用ENTRYPOINT将CMD替换掉,则在运行容器时指定的初始命令无效,依旧使用 dockerfile中的初始命令
小结:
ENTRYPOINT:当我们项目上线后,防止用户更改初始命令导致容器无法运行
CMD :利于我们调试
建议:
开发调试阶段使用CMD,上线使用ENTRYPOINT
dockerfile健康检查:
https://www.qstack.com.cn/
通过dockerfile构建一个最简单的docker镜像
1、创建dockerfile文件
先创建一个文件夹,该文件夹名建议写成我们将要构建的镜像名,然后在改文件夹下创建一个dockerfile文件,这里文件名必须是dockerfile
2、编写dockerfile
FROM centos:6
RUN echo '192.168.0.102 mirrors.aliyum.com' >>/etc/hosts
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
RUN yum install openssh-server -y
RUN service sshd restart
RUN echo '123' |passwd --stdin root
CMD ["/usr/sbin/sshd","-D"]
3、构建镜像
docker build -t centos6_ssh:v2 ./
参数说明:
-t 指定镜像的名称合版本
./ dockerfile的路径(这里可以是相对路劲也可以是绝对路径,这里使用了相对路径)
4、使用 docker images 查看新构建的镜像
5、测试
1、使用新创将的镜像启动一个容器:
docker run -d -p 1024:22 centos6_ssh:v2
# 由于我们在dockerfile中写了 CMD ,即指定了容器的初始命令,所以这里不用再次指定
2、查看镜像的初始命令
docker ps -a -l
3、ssh登录容器进行验证
ssh root@10.0.0.51 -p 1024
自动构建镜像的步骤:
1、手动构建一个镜像 # 直接编写dockerfiel很难考虑到每个步骤,以及所依赖的模块
2、编写dockerfile # 参考手动构建镜像的历史命令
3、构建镜像
4、测试
排错:
容器死了:docker logs 容器ID
容器存活:docker run -it image_name CMD
练习:
写一个dockerfile,制作一个kodexplorer网盘docker镜像。nginx + php-fpm (httpd + php)
1、手动构建:(基于apache)
1、创建一个容器
docker run -it -p 80:80 centos:6.9 /bin/bash
2、换Base源(目的是为了安装服务时下载速度快),这一也步可以省略不做
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
3、安装php服务
yum install php -y
4、下载kodexplorer并解压
cd /var/www/html (php默认的站点目录)
wget http://static.kodcloud.com/update/download/kodexplorer4.40.zip
yum install unzip -y (解压发现没有unzip,于是安装unzip)
unzip kodexplorer4.40.zip
chown -R apache:apache .
5、测试:
在浏览器测试,输入:10.0.0.51/index.php
发现错误,缺少这2个包: php-gd、php-mbstring
安装 yum install php-gd php-mbstring -y
重新测试 ==> 正常
2、编写dockerfile
将手动构建的命令整合,如下:
dockerfile
FROM centos:6.9
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo && \
yum install php unzip php-gd php-mbstring -y # 将所有包放在一起安装
WORKDIR /var/www/html/ # 手动构建使用cd切换到站点目录,这里我们使用dockerfile命令指定工作目录
ADD kodexplorer4.40.zip . # ADD将宿主机上的文件添加到docker
RUN unzip kodexplorer4.40.zip
RUN chown -R apache:apache .
ADD init.sh /init.sh
EXPOSE 80 # 更加规范
ADD test.sh /test.sh # 健康检查脚本
ENTRYPOINT ["/bin/bash","/init.sh"] # 将CMD换成ENTRYPOINT
启动脚本
init.sh
#!/bin/bash
service httpd restart
tail -F /var/log/httpd/access_log
3、构建镜像
docker build -t kod:v1 .
4、测试
1、使用新构建的镜像创建一哥容器
docker run -d -p 81:80 kod:v1
2、浏览器验证:10.0.0.51:81/index.php