docker基础命令以及制作镜像

docker 基础

镜像:docker的镜像是创建容器的基础,可以理解为是一个面向docker容器引擎的只读模板,比如:一个镜像可以是一个完整的centos操作系统环境,称为一个centos镜像;可以是一个安装了MySQL的应用程序,称为一个MySQL镜像等等。

容器:docker的容器是从镜像创建的运行实例,它可以被启动、停止和删除。所创建的每一个容器都是相互隔离、互不可见的,可以保证平台的安全性。

仓库:docker仓库是用来集中保存镜像的地方。

查看docker是否安装

yum list installed | grep docker

卸载旧版本

较旧的 Docker 版本称为 docker 或 docker-engine 。如果已安装这些程序,请卸载它们以及相关的依赖项。

$ sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

设置仓库

使用 Docker 仓库进行安装

在新主机上首次安装 Docker Engine-Community 之前,需要设置 Docker 仓库。之后,您可以从仓库安装和更新 Docker。

安装所需的软件包。yum-utils 提供了 yum-config-manager ,并且 device mapper 存储驱动程序需要 device-mapper-persistent-data 和 lvm2。

$ sudo yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2

使用以下命令来设置稳定的仓库。

使用官方源地址(比较慢)

$ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com**/**linux**/**centos**/**docker-ce.repo

可以选择国内的一些源地址:

阿里云

$ sudo yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

清华大学源

$ sudo yum-config-manager \
    --add-repo \
    https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo

安装 Docker Engine-Community

安装最新版本的 Docker Engine-Community 和 containerd,或者转到下一步安装特定版本:

$ sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin

如果提示您接受 GPG 密钥,请选是。

Docker 安装完默认未启动。并且已经创建好 docker 用户组,但该用户组下没有用户。

安装指定版本:

通过其完整的软件包名称安装特定版本,该软件包名称是软件包名称(docker-ce)加上版本字符串(第二列),从第一个冒号(:)一直到第一个连字符,并用连字符(-)分隔。例如:docker-ce-18.09.1。

$ yum list docker-ce --showduplicates | sort -r

docker-ce.x86_64  3:18.09.1-3.el7                     docker-ce-stable
docker-ce.x86_64  3:18.09.0-3.el7                     docker-ce-stable
docker-ce.x86_64  18.06.1.ce-3.el7                    docker-ce-stable
docker-ce.x86_64  18.06.0.ce-3.el7                    docker-ce-stable

$ sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io

卸载 docker

删除安装包:

$ yum remove docker-ce

删除镜像、容器、配置文件等内容:

$ rm -rf /var/lib/docker

常用指令

docker的镜像文件存放在/var/lib/docker文件夹中。

#  启动
$ sudo systemctl start docker

#  设置开机启动
$ systemctl enable docker

Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/system/docker.service.

#  配置镜像加速 daemon.json 文件不存在则直接创建
$ vim /etc/docker/daemon.json
{
	"bridge":"newnet",
	"insecure-registries":[
		"registry.luntek-inc.com"
	],
	"registry-mirrors": [
		"https://registry.docker-cn.com",
		"http://hub-mirror.c.163.com",
		"https://docker.mirrors.ustc.edu.cn"
	]
}
#  注:insecure-registries属性值代表私有仓库的地址,你需要改成你自己的私有仓库地址,registry-mirrors配置的是国内的docker镜像仓库地址,让下载镜像速度更快。
#  bridge 属性 用于修改默认网桥(Docker自定义网桥)
#  Docker自定义网桥也可以在启动docker服务的时候,使用 -b BRIDGE或--bridge=BRIDGE来指定使用的网桥。

#  重新加载配置文件并且重启docker
$ systemctl daemon-reload 
$ systemctl restart docker
#  docker 重启后 查看docker配置的私有仓库地址是否生效
$ docker info

# 查看docker 版本
$ docker version

# 搜索镜像 docker search 命令,搜索远端官方仓库中的共享镜像。
$ docker search lamp
# 获取镜像 使用docker pull 命令从网络下载镜像到本地使用,默认是下载最新版本的。
# 命令格式: docker pull 仓库名称[:标签]
$ docker pull nickistre/centos-lamp

# 查看本地所有镜像
$ docker images
# 回显信息中 REPOSITORY--镜像属于的仓库 TAG--镜像的标签信息,标记同一个仓库中的不同镜像。
# IMAGE ID-- 镜像的唯一ID号,唯一标识了该镜像 CREATED--镜像创建时间 VIRTUAL SIZE--镜像大小

# 获取镜像的详细信息
# 命令格式: docker inspect 镜像ID
$ docker inspect a0760f339197

# 为本地镜像添加新的标签
# 命令格式: docker tag 名称:[标签] 新名称:[新标签]
# 本地镜像nickistre/centos-lamp 添加新的名称为 lamp 新的标签为lamp
$ docker tag nickistre/centos-lamp lamp:lamp

# 删除镜像 使用docker rmi 命令
# 命令格式: docker rmi 仓库名称:标签  或者  docker rmi 镜像ID
$ docker rmi lamp:lamp
# 注意:当一个镜像有多个标签的时候,docker rmi只是删除该镜像多个标签中的指定标签,不会影响镜像文件。
# docker rmi 后跟镜像ID时,必须确保该镜像没有被容器使用才能进行,删除时系统会先删除掉指向该镜像的所有
# 标签,然后删除该镜像文件本身。

# 存出镜像
# 当需要把一台机器上的镜像迁移到另一台机器上的时候,需要将镜像保存成本地文件,这一过程叫存出镜像。
# 命令格式: docker save -o 存储文件名 存储的镜像
# 将本地的nickistre/centos-lamp镜像存出位文件 lamp
$ docker save -o lamp nickistre/centos-lamp

# 载入镜像
# 将存出的镜像从 A 机器拷贝到 B 机器,需要在 B 机器上使用该镜像,就可以将导出文件导入到 B 机器
# 的镜像库中,这一过程叫载入镜像。
# 命令格式: docker load <存出的文件 或者 docker --input 存出的文件
$ docker load <lamp
$ docker --input lamp


#  docker参数:
#  运行   -it 容器交互界面  --rm 容器退出删除容器
#  --restart=always : 开机启动,失败也会一直重启;
#  --restart=on-failure:10 : 表示最多重启10次
#  –restart具体参数值详细信息:
#   1.no - 容器退出时,不重启容器;
#   2.on-failure - 只有在非0状态退出时才从新启动容器;
#   3.always - 无论退出状态是如何,都重启容器

$ docker run -it --rm ubuntu:16.04 /bin/bash
$ docker update --restart=always  容器名字或者容器ID  //如果是已经在运行中的容器要加上该参数

#  docker修改容器参数
$ docker update -m 500m --memory-swap -1 f669487f0804

# 列出容器
$ docker ps
# -a 显示所有的容器,包括未运行的
# -n 列出最近创建的n个容器
# -q 静默模式,只显示容器编号

# 获取容器的日志
$ docker logs -f 容器名或容器ID
# -f 跟踪日子输出
# --tail 仅列出最新N条容器日志

# 获取docke容器的元数据 -f 指定返回值的末班文件
$ docker inspect 容器名或容器ID

# 删除一个或多个容器
$ docker rm 容器名或容器ID
# -f 强制删除,通过SIGKILL信号删除一个正在运行的容器
# -v 删除容器和它在主机的映射目录 eg: docker rm -f -v tomcat
# eg:删除所有已停止的容器 docker rm $(docker ps -a -q)

#  查看容器
$ docker container ls --all

#  容器信息
$ docker system df

#  启动容器
$ docker start imagesId

#  查询日志
$ docker logs imagesId

#  后台运行 -d
$ docker run -d images:tag

#  端口映射: -p (宿主机:容器端口)
#  容器名字: --name 
#  表示运行容器: -i
#  容器启动后进去命令行: -t
#  创建守护式容器后台运行: -d
#  目录双向绑定:-v 宿主机目录:容器目录  权限不足使用:--privileged=true

#  多目录: -v 宿主机目录:容器目录 -v 宿主机目录:容器目录
#  匿名挂载: -v 容器目录 容器外对应目录会在:/var/lib/docker/volumes中生成

#  默认数据卷: /var/lib/docker/volumes

#  查看容器详细信息 文件信息 mounts:[]
$ docker inspect 容器名

#  运行容器
$ docker run --name nignx -d -p 80:80 nginx
#  进入容器
$ docker exec -it (imagesId/name)

# 容器删除
# 命令格式: docker rm 容器ID/名称
$ docker rm lamp
# 注意:如果要删除一个正在运行的容器,可以添加 -f 选项强制删除,但建议先将容器停止再删除。

#  文件拷贝
$ docker cp 宿主机 镜像:文件路径
$ docker cp /soft/app.tar centos:/usr/local/

#  查看镜像层组成
$ docker history ubuntu:14.04 

本地现有的docker镜像进行测试上传到dockerhub上

#  查看当前docker镜像
$ docker images

#  将 docker_vue镜像进行上传到dockerhub仓库中

#  1、首选将镜像打上标签 
#  语法:docker tag 镜像id dockerhub账号名称/dockerhub仓库名称:仓库标签
$ docker tag 0ae3cc39ae0d xx123/flask:vue1.0

#  2、登陆dockerhub账号 输入dockerhub账号密码后 登录成功
$ docker login

#  3、上传镜像到dockerhub仓库中 上传成功后 登录dockerhub查看
#  语法:docker push dockerhub账号/dockerhub仓库名称:dockerhub标签名
$ docker push xx123/flask:vue1.0

#  4、拉取镜像命令仓库中会有拉取命令(dockerhub仓库->Tags选项中),需要删除本地的镜像
$ docker pull xx123/flask:vue1.0

#  5、测试镜像是否正常运行
$ docker run -tid -p 8888:80 镜像id

docker run 参数详解

命令格式:docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

Usage: Run a command in a new container

中文意思为:通过run命令创建一个新的容器(container)

常用选项说明

-d, --detach=false, # 指定容器运行于前台还是后台,默认为false

-i, --interactive=false, # 打开STDIN,用于控制台交互

-t, --tty=false, # 分配tty设备,该可以支持终端登录,默认为false

-u, --user="", # 指定容器的用户

-a, --attach=[], # 登录容器(必须是以docker run -d启动的容器)

-w, --workdir="", # 指定容器的工作目录

-c, --cpu-shares=0, # 设置容器CPU权重,在CPU共享场景使用

-e, --env=[],# 指定环境变量,容器中可以使用该环境变量(向容器内传递环境变量,启动容器时用户可以动态传参)

-m, --memory="", # 指定容器的内存上限

-P, --publish-all=false, # 指定容器暴露的端口

-p, --publish=[], # 指定容器暴露的端口

-h, --hostname="", # 指定容器的主机名

-v, --volume=[], # 给容器挂载存储卷,挂载到容器的某个目录

--volumes-from=[], # 给容器挂载其他容器上的卷,挂载到容器的某个目录

--cap-add=[], # 添加权限,权限清单详见:http://linux.die.net/man/7/capabilities

--cap-drop=[], # 删除权限,权限清单详见:http://linux.die.net/man/7/capabilities

--cidfile="", # 运行容器后,在指定文件中写入容器PID值,一种典型的监控系统用法

--cpuset="", # 设置容器可以使用哪些CPU,此参数可以用来容器独占CPU

--device=[], # 添加主机设备给容器,相当于设备直通

--dns=[], # 指定容器的dns服务器

--dns-search=[], # 指定容器的dns搜索域名,写入到容器的/etc/resolv.conf文件

--entrypoint="", # 覆盖image的入口点

--env-file=[], # 指定环境变量文件,文件格式为每行一个环境变量

--expose=[], # 指定容器暴露的端口,即修改镜像的暴露端口

--link=[], # 指定容器间的关联,使用其他容器的IP、env等信息

--lxc-conf=[], # 指定容器的配置文件,只有在指定--exec-driver=lxc时使用

--name="", # 指定容器名字,后续可以通过名字进行容器管理,links特性需要使用名字

--net="bridge", # 容器网络设置:

# bridge 使用docker daemon指定的网桥

# host //容器使用主机的网络

# container:NAME_or_ID ># 使用其他容器的网路,共享IP和PORT等网络资源

# none 容器使用自己的网络(类似--net=bridge),但是不进行配置

--privileged=false, # 指定容器是否为特权容器,特权容器拥有所有的capabilities,container内的root拥有真正的root权限。否则,container内的root只是外部的一个普通用户权限。甚至允许你在docker容器中启动docker容器。

--restart="no", # 指定容器停止后的重启策略:

# no:容器退出时不重启

# on-failure:容器故障退出(返回值非零)时重启

# always:容器退出时总是重启

--rm=false, # 指定容器停止后自动删除容器(不支持以docker run -d启动的容器)

--sig-proxy=true, # 设置由代理接受并处理信号,但是SIGCHLD、SIGSTOP和SIGKILL不能被代理

示例:

# 运行一个在后台执行的容器,同时,还能用控制台管理:
docker run -i -t -d ubuntu:latest

# 运行一个带命令在后台不断执行的容器,不直接展示容器内部信息:
docker run -d ubuntu:latest ping www.docker.com

# 运行一个在后台不断执行的容器,同时带有命令,程序被终止后还能重启继续跑,还能用控制台管理,
docker run -d --restart=always ubuntu:latest ping www.docker.com

# 为容器指定一个名字,
docker run -d --name=ubuntu_server ubuntu:latest

# 容器暴露80端口,并指定宿主机80端口与其通信(: 之前是宿主机端口,之后是容器需暴露的端口),
docker run -d --name=ubuntu_server -p 80:80 ubuntu:latest

# 指定容器内目录与宿主机目录共享(: 之前是宿主机文件夹,之后是容器需共享的文件夹),
docker run -d --name=ubuntu_server -v /etc/www:/var/www ubuntu:latest

修改 docker 容器的启动参数

docker 容器在启动时指定了 cmd 启动参数和挂载目录等配置。后来因为业务需要,需要变更启动参数或挂载目录等信息。

1、停止所有 docker 容器
$ sudo docker stop $(docker ps -a | awk '{ print $1}' | tail -n +2)

2、停止 docker 服务(不同操作系统命令所有区别)
$ sudo systemctl stop docker

# 这一步很重要,否则修改无法成功,你会发现修改后配置又回去了。

3、找到容器ID后,进入容器配置文件所在目录
# 输出容器的长ID
$ sudo docker ps -a --no-trunc --format "table {{.ID}}\t{{.Image}}\t{{.Names}}" |grep rancher-agent

# 配置文件所在目录为 /var/lib/docker/containers/容器的长ID/

4、查看和修改配置文件 hostconfig.json 和 config.v2.json
查看这两个配置文件内容,根据自己实际需要修改的内容对其进行修改即可,注意修改之前进行备份一下。

5、最后启动 docker 服务再启动容器即可生效。

安装portainer

#  中文版的
$ docker pull 6053537/portainer-ce 
$ docker volume create portainer_data
$ docker run -d --name portainer -p 9000:9000 --restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
6053537/portainer-ce
# 需要将docker.sock 文件绑定到容器中

配置ip

# shell 脚本
#!/bin/bash
for i in {1..99}
do
        `nmcli connection modify ens3 +ipv4.addresses 172.16.61.${i}`
done

`nmcli con up ifname ens3`

nmcli connection modify 可以修改现有连接

  • con 可以写成 c 到 connection之间的字段

  • mod 可以写成 m 到 modify 之间的字段

    nmcli connection modify
    nmcli connec modify
    nmcli conne modif
    nmcli con mod
    nmcli co mo
    nmcli c m
    nmcli c modify
    nmcli connection m
    
  • `ipv4.可以接 [method,dns,dns-search,dns-options,dns-priority,addresses,gateway,routes,route-metric,route-table,routing-rules,ignore-auto-routes,ignore-auto-dns,dhcp-client-id,dhcp-iaid,dhcp-timeout,dhcp-send-hostname,dhcp-hostname,dhcp-fqdn,dhcp-hostname-flags,never-default,may-fail,required-timeout,dad-timeout,dhcp-vendor-class-identifier,dhcp-reject-servers].

    • ipv4.method的可选]值有 [auto, link-local, manual, shared, disabled] , 最简可写成ipv.me
    • ipv4.addresses设置ip地址,最简可写成ipv4.a,可设置多个地址,以逗号分割,也可以多次用+ipv4.a, ipv4.a可以设置多个(逗号分隔,可以有空格),但只能出现一次, +ipv4.a可以设置多个(逗号分隔)可以出现多次。
    • ipv4.x前面可以加(加号或减号+/-),ipv4.x表示设置+ipv4.x表示新增,-ipv4.x表示移除,一句中只能出现一次ipv4.x,后面的ipv4.x会覆盖前面的ipv4.x, 一句中可以出现多次+ipv4.x-ipv4.x

Docker网络管理以及固定ip

docker网络工作原理

docker创建容器时默认采用bridge网络,自行分配ip,不允许自己指定

docker服务启动时会创建一个名为docker0的网桥,在启动容器的时候,会在宿主机和容器内各生成一个虚拟网卡。宿主机和容器内的虚拟网卡默认是连接到docker0这个网桥上的。所以容器可以和宿主机或其他容器网络通信。Docker0的默认IP为172.17.0.1

启动一个容器并进入,发现容器的ip172.17.0.2,ping宿主机发现是可以ping通的

$ ping 172.17.0.1

在宿主机上查看桥接信息

$ brctl show

发现这个docker0连上了一块虚拟网卡,这块虚拟网卡就是用来连接容器的。

再开一个容器,发现docker0上连接了两款虚拟网卡,分别用于连接两个容器。

用ip link show 这个命令也可以看到这两块网卡。

docker是如何连通宿主机以外的网络,外网又是如何可以访问到容器呢?

很简单,就是通过iptables的nat功能(端口转发)。

docker中使用-p <外网端口>:<内网端口>来实现端口转发,如:docker container run -d --rm --name web -p 8080:80 nginx。此过程中实际是iptables在生效。查看iptables(iptables -t nat -nvxL | grep -A 5 'Chain DOCKER')信息发现,iptables增加了DNAT(Destination NAT)规则,此规则将宿主机的8080转发为172.17.0.4即容器nginx 80端口。

#  https://blog.csdn.net/weixin_43631940/category_12069036.html

#  查看iptables的nat配置
$ iptables -t nat -L

Chain POSTROUTING (policy ACCEPT)
target			prot	opt		source			destination
MASQUERADE		all		--		172.17.0.0/16	anywhere
# 此处表示源地址转换,意思是容器访问外网的时候,源地址转换为宿主机外网网卡的地址


Chain DOCKER (2 references)
target	prot	opt		source			destination
DMAT	tcp		--		anywhere		anywhere	 tcp dpt:mysql to 172.17.0.3:3306
#  此处表示目的地址转换,意思是外网访问宿主机3306端口时,iptables外将目的地址转为容器的IP地址。

1、Docker有四种网络模式

hosts:容器和主机共享一个网络
container:容器和另外一个容器一个网络
none:不进行网络连接
bridge:默认配置,桥接模式

2、查看docker默认network

$ docker network ls

3、docker 默认的网络模式网关是127.17.0.1,我们可以创建新的bridge网络供容器使用,并且指定网段。

$ docker network create --driver bridge --subnet=172.16.61.1/24 --gateway 172.16.61.1 newnet
# --subnet=172.16.61.1/24 将newnet的网段设为172.16.61.1/24
# --gateway 172.16.61.1 将newnet的网关设为172.16.61.1(宿主机会取得这个地址) 

# 查看新创建的网络信息
$ docker network inspect newnet

注意:网段进来不要跟主机重复。

166.166.0.0/16 其中末尾的16表示最多支持65535个ip地址,范围是166.166.0.2到166.166.255.255。可以改为24,最多支持254个ip,方位166.166.0.2到166.166.0.255。

newnet是创建的网络名称,可以自己改变。

4、创建容器并添加参数是可以指定容器的网络和ip的

--net newnet --ip 172.16.具体值.具体值

# 创建容器且指定网络ip
$ docker run -itd --network=newnet --ip x.x.x.8 --name containerName imageName 

# 启动报错:WARNING:IPv4 forwarding is disabled. Networking will not work.
# 是没有开启转发,网桥配置完成后,需要开启转发,不然容器启动后,就会没有网络,配置/etc/sysctl.conf,添加
# net.ipv4.ip_forward=1
$ vim /etc/sysctl.conf

# 重启服务,让配置生效
$ systemctl restart network  // 不存在的话使用 $ nmcli c reload  命令

# 查看是否成功,如果返回为 net.ipv4.ip_forwar=1 则表示成功
$ systcl net.ipv4.ip_forward


$ docker network rm newnet # 删除创建的网桥

也可以修改已经创建的容器的网络

# 解除容器原先的网络
$ docker network disconnect 网络 容器
eg: $ docker newwork disconnect bridge mysql8

# 重新绑定网络和指定ip 也可以不指定ip
$ docker network connect 网络 --ip 166.166.0.3 容器

# 重启容器
$ docker restart 容器

# 查看结果
$ docker inspect 容器

修改默认网桥 docker0(自定义网桥)

背景

默认情况下启动docker之后会自己创建一个名为 docker0的网桥。但是里面的ip配置可能不是自己期望或是与某些公司内部的网关冲突了,造成不必要的麻烦。

如何解决?

修改默认的配置文件 /etc/docker/daemon.json对Docker进行配置。

如果服务已经开始需要先停止服务,并删除旧的网络。

$ sudo service docker stop
$ sudo ip link set dev docker0 down
$ sudo brctl delbr docker0

修改 /etc/docker/daemon.json以下代码是我的范例

{
  "bip": "192.188.0.1/16",
  "registry-mirrors": [
    "https://a73cc22x.mirror.aliyuncs.com",
    "https://hub-mirror.c.163.com",
    "http://c0d14726.m.daocloud.io",
    "https://registry.aliyuncs.com"
  ]
}

重启Doker服务:

$ sudo systemctl start docker

查看配置是否成功

$ ifconfig docker0
docker0   Link encap:Ethernet  HWaddr 02:42:38:60:08:25
          inet addr:192.188.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

另外一种操作

类似的也需要删除旧的docker0如果已经启动docker服务先关闭了再删除。

手动创建一个新的网桥名称为 bridge0

$ sudo brctl addbr bridge0
# add表示添加,dev表示设备,bridge0是bridge0网卡,192.188.0.1为添加的ip地址,24表示子网掩码,与255.255.255.0相同,整个命令表示给bridge0网卡上添加了一个192.188.0.1子网掩码为 255.255.255.0的ip地址。
$ sudo ip addr add 192.188.0.1/24 dev bridge0
$ sudo ip link set dev bridge0 up		 # 开启或关闭接口

查看确认网桥创建并启动。

$ ip addr show bridge0
4: bridge0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state UP group default
    link/ether 66:38:d0:0d:76:18 brd ff:ff:ff:ff:ff:ff
    inet 192.188.0.1/16 scope global bridge0
       valid_lft forever preferred_lft forever

在 Docker 配置文件/etc/docker/daemon.json 中添加如下内容,即可将 Docker 默认桥接到 创建的网桥上。

(也可以在启动docker服务的时候,使用 -b BRIDGE 或 --bridge=BRIDEGE 来指定使用的网桥。)

 { 
     "bridge": "bridge0", 
 }

再次启动docker服务。

如何查看电脑的路由信息,确定自己到底哪个网关冲突了?

执行以下命令:

$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.16.3.1      0.0.0.0         UG    0      0        0 enp0s31f6
192.16.3.0      0.0.0.0         255.255.255.0   U     0      0        0 enp0s31f6
192.38.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-8658c245b375
192.128.0.0     0.0.0.0         255.255.0.0     U     0      0        0 br-18e510164f90
192.133.0.0     0.0.0.0         255.255.0.0     U     0      0        0 br-d6fb5b3db5a7
192.188.0.0     0.0.0.0         255.255.0.0     U     0      0        0 docker0

网桥工具安装

linux工作在网桥模式,必须安装网桥工具bridge-utils:

# 下载地址:https://mirrors.edge.kernel.org/pub/linux/utils/net/bridge-utils/
运行命令: $ yum install -y bridge-utils
或下载 bridge-utils-1.7.1.tar.gz
# 1、解压缩
$ tar zxvf bridge-utils-1.7.1.tar.gz && cd bridge-utils-1.7.1

# 2、编译安装
# 注意:-bash: autoconf:未找到命令 直接yum -y install autoconf就可以了
$ autoconf && ./configure && make
$ make install

brctl 命令用于设置、维护和检测linux内核中的以太网网桥配置。

常用参数:

addbr		// 创建网桥  eg: brctl addbr br7
delbr		// 删除网桥	 eg: brctl delbr br7
addif		// 将网卡接口接入网桥	eg: brctl addif br7 eth0
delif		// 删除网桥接入的网卡接口 eg: brctl delif br7 eth0
show		// 查询网桥信息		eg: brctl show br7
stp {on|off}// 启动禁用STP		 eg: brctl stp br7 off/on
showstp		// 查看网桥STP信息	eg: brctl showstp br7
setfd		// 设置网桥延迟		eg: brctl setfd br7 6
showmacs	// 查看mac信息		 eg: brctl showmacs br7

网络设置:

1、命令设置:brctl addbr

2、编辑文件配置网络

在/etc/sysconfig/network-scripts/目录下创建一个文件,文件名格式为ifcfg-name,name处可以随便起名

DEVICE=eth0   设备
ONBOOT=yes    在网络启动时自动**
BOOTPROTO=none    获取ip的方式
IPADDR=172.25.254.110  IP地址
NETMASK=255.255.255.0  子网掩码,也可以写为PREFIX=24

# 上面的网络是静态网络,要动态获取网路,可以编辑为dhcp自动获取网络:

#动态网络配置
DEVICE=eth0
ONBOOT=yes
BOOTPROTO=dhcp    获取IP的方式为dhcp

# systemctl restart NetworkManager
#service NetworkManager restart

制作Docker镜像

概述

docker镜像的创建方法:

  • 基于已有镜像创建
  • 基于本地模板创建
  • 基于Dockerfile创建
    • 建立工作目录
    • 创建并编写Dockerfile文件
    • 编写执行脚本内容
    • 创建测试页面
    • 使用Dockerfile生成镜像
    • 使用新的镜像运行容器
    • 将镜像上传到仓库中

docker的数据管理:

  • 数据卷
    • 创建数据卷
    • 挂载主机目录作为数据卷
  • 数据卷容器

docker网络通信:

  • 端口映射
  • 容器互联
    • 创建源容器
    • 创建接收容器
    • 测试容器互联

基于已有镜像创建

基于已有镜像创建主要使用 docker commit命令。实质就是把一个容器里面运行的程序以及该程序的运行环境打包起来生产新的镜像。

命令格式: docker commit [选项] 容器ID/名称 仓库名称:[标签]

常用选项:-m:说明信息 -a:作者信息 -p:生成过程中停止容器的运行

$ docker commit -m "new" -a "daoke" bf259d1747a7 daoke:test

# 创建完成后返回新创建镜像的ID信息。
# 查看本地镜像列表可以看到新创建的镜像信息:
$ docker images|grep daoke

基于本地模板创建

通过导入操作系统模板文件可以生成镜像,模板可以从OPENVZ开源项目下载,下载地址为

http://openvz.org/Download/template/precreated

命令格式:cat <template-file> | docker import - <new-image-name>:<tag>

$ wget http://openvz.org/Download/template/precreated/debian-7.0-x86-minimal.tar.gz
$ cat debian-7.0-x86-minimal.tar.gz|docker import - daoke:new

# 查看本地镜像列表可以看到新创建的镜像信息
$ docker images|grep new

基于dockerfile创建

Dockerfile是由一组指令组成的文件,其中每条指令对应linux中的一条命令,Docker程序将读取Dockerfile中的指令生成指定镜像。

Dockerfile结构大致分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。

Dockerfile每行支持一条指令,每条指令可携带多个参数,支持使用 #号开头的注释。

在编写Dockerfile时,有严格的格式需要遵循:第一行必须使用FROM指令指明所基于的镜像名称,之后使用MAINTAINER指令说明维护该镜像的用户信息,然后是镜像操作相关指令,如RUN指令,每运行一条指令,都会给基础镜像添加新的一层,最后使用CMD指令,来指定启动容器时要运行的命令操作。

指令 含义
FROM镜像 指定新镜像所基于的镜像,第一条指令必须为FROM指令,每创建一个镜像就需要一条FROM指令
MAINTAINER名子 说明新镜像的维护人信息
RUN命令 在所基于的镜像上执行命令,并提交到新的镜像中
CMD ["要运行的程序","参数1","参数2"] 指定启动容器时要运行的命令或者脚本,Dockerfile只能有一条CMD命令,如果指定多条则只有最后一条被执行
EXPOSE 端口号 指定新镜像加载到Docker时要开启的端口
ENV 环境变量 变量值 设置容器中的环境变量。RUN指令和容器中运行的应用会直接使用ENV指令定义的环境变量。
ADD 源文件/目录 目标文件/目录 将源文件复制到目标文件,源文件要与Dockerfile位于相同目录中,或者是一个URL,.tar文件会自动解压。
COPY 源文件/目录 目标文件/目录 将本地主机上的源文件复制到目标地点,源文件要与Dockerfile在相同目录中
VOLUME["目录"] 在容器中创建一个挂载点,通过VOLUME指令创建的挂载点,无法指定主机上对应的目录,是自动生成的。
USER 用户名/UID 指定运行容器时的用户
WORKDIR 路径 为后续的RUN、CMD、ENTRYPOINT、COPY和ADD等指令指定工作目录
ONBUILD 指令 指定所生成的镜像作为一个基础镜像时所要运行的命令

使用Dockerfile创建镜像并在容器中运行的案例:

首先需要建立目录,作为生成镜像的工作目录,然后分别创建并编写Dockerfile文件、需要运行的脚步文件以及要复制到容器中的文件。

# 1. 建立工作目录
$ makdir apache
$ cd apache
# 2.创建并编写Dockerfile文件
$ vim Dockerfile
# 基于的基础镜像centos
FROM centos
# 维护该镜像的用户信息
MAINTAINER the centos
# 镜像操作指令安装apache软件包
RUN yum -y update
RUN yum -y install httpd
# 开启80端口
EXPOSE 80
# 复制网站首页文件
ADD index.html /var/www/html/index.html
# 将执行脚本复制到镜像中
ADD run.sh /run.sh
RUN chmod 775 /run.sh
# 启动容器时执行脚本
CMD ["run.sh"]

#3.编写执行脚本内容
$ vim run.sh
#!/bin/bash
rm -rf /run/httpd/*  // 清理httpd的缓存
exec /usr/bin/apachctl -D FOREGROUND  // 启动apache服务

# 4. 使用Dockerfile生成镜像
# 使用docker build 命令来创建镜像
$ docker build -t http:centos .

# 5.使用新的镜像运行容器
$ docker run -d -p 8080:80 httpd:centos
# -p 选项实现从本地端口8080到容器中80端口的映射

# 6.将镜像上传到仓库中
$ docker login

# 输入账号密码登录成功 将新创建的镜像上传到公共仓库中
$ docker push httpd:centos

docker的数据管理

管理Docker容器中的数据主要有两种方式:数据卷和数据卷容器。

数据卷是一个供容器使用的特殊目录,位于容器中,可将宿主机的目录挂载到数据卷上,对数据卷的修改操作立刻可见,并且更新数据不会影响镜像,从而实现数据在宿主机与容器之间的迁移。数据卷的使用类似于Linux下对目录进行的mount操作。

1、创建数据卷

在 docker run命令中使用 -v 选项可以在容器内创建数据卷。多次使用 -v 选项可创建多个数据卷。使用 --name 选项可以给容器创建一个友好的自定义名称。

# 创建一个名为web的容器,并且创建两个数据卷分别挂载到 /data1 与 /data2目录上
$ docker run -d -v /data1 -v /data2 --name web httpd:centos

2、挂载主机目录作为数据卷

使用 -v 选项可以在创建数据卷的同时,将宿主机的目录挂载到数据卷上使用,以实现主机与容器之间的数据迁移。

注意:宿主机本地目录的路径必须使用绝对路径,如果路基不存在,Docker会自动创建相应的路径。

$ docker run -d -v /var/www:/data1 --name web1 httpd:centos

3、数据卷容器

如果需要再容器之间共享一些数据,最简单的方法就是使用数据卷容器。数据卷容器就是一个普通的容器,专门提供数据卷给其他容器使用。

使用方法:首先,需要创建一个容器作为数据卷容器,之后在其他容器创建时用 --volumes-from 挂载数据卷容器中的数据使用。

使用前面创建好的数据卷容器web,其中所创建的数据卷分别挂载到了 /data1 与 /data2目录上, 使用 --volumes-from 来挂载 web容器中的数据到新的容器,新的容器名为db1

$ docker run -it --volumes-from web --name db1 httpd:centos /bin/bash

我们在 db1 容器数据卷 /data1 目录中创建一个文件 file。在 web 容器中的 /data1目录中可以查看到它。

这样就可以通过数据卷容器实现容器之间的数据共享。

docker网络通信

1、端口映射

在启动容器时,如果不指定对应的端口,在容器外将无法通过网络来访问容器内的服务。Docker提供端口映射机制来将容器内的服务提供给外部网络访问,实质上就是将宿主机的端口映射到容器中,使得外部网络访问宿主机的端口便可访问容器内的服务。

2、容器互联

容器互联是通过容器的名称在容器间建立一条专门的网络通信隧道从而实现容器的互联。简单点说,就是会在源容器和接收容器之间建立一条隧道,接收容器可以看到源容器指定的信息。

在运行 docker run 命令时使用 --link 选项可以实现容器之间的互联通信。

格式: --link name:alias

其中 name 是要连接的容器名称,alias 是这个连接的别名。

容器互联是通过容器的名称来执行的,--name选项可以给容器创建一个友好的名称,这个名称是唯一的。

# 1、创建源容器
# -P(大写) 选项实现随机映射
# 创建容器A  容器名为 web1
$ docker run -d -P --name web1 httpd:centos

# 2、创建接收容器
# 创建容器B,容器名为 web2,使用  --link 指定连接容器以实现容器互联
$ docker run -d -P --name web2 --link web1:web1 httpd:centos

# 3、测试容器互联
# 最简单的检测方法是进入容器,使用 ping 命令查看容器是否能相互连通。
$ docker exec -it web2 /bin/bash
$ ping web1

docker 构建LNMP镜像

# 1. 下载基础镜像并创建工作目录
$ docker pull lemonbar/centos6-ssh
$ mkdir lnmp
$ cd lnmp

# 2. 创建Dockerfile文件
$ vim Dockerfile
# 基础镜像
FROM lemonbar/centos6-ssh
# 维护该镜像的用户信息
MAINTAINER the centos
# 配置nginx 的 yum 源
RUN rpm -ivh http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
# 安装 nginx
RUN yum install -y nginx
# 修改nginx配置文件,使之支持 php
RUN sed -i '/^user/s/nginx/nginx\ nginx/g' /etc/nginx/nginx.conf
RUN sed -i '10cindex index.php index.html index.htm;' /etc/nginx/conf.d/default.conf
RUN sed -i '30,36s/#//' /etc/nginx/conf.d/default.conf
RUN sed -i '31s/html/\/usr\/share\/nginx\/html/' /etc/nginx/conf.d/default.conf
RUN sed -i '/fastcgi_param/s/script/usr\/share\/nginx\/html/' /etc/nginx/conf.d/default.conf
# 安装mysql和php
RUN yum install -y mysql mysql-server php php-mysql php-fpm
# 修改php-fpm配置文件允许nginx访问
RUN sed -i '/^user/s/apache/nginx/g' /etc/php-fpm.d/www.conf
RUN sed -i '/^group/s/apache/nginx/g' /etc/php-fpm/www.conf
# mysql数据库授权
# shell脚本操作mysql,使用mysql -e 参数可以执行各种sql的操作(创建、删除、增删改查)。
RUN /etc/init.d/mysqld start &&\
mysql -e "grant all privileges on *.* to 'root'@'%' identified by '123456';" &&\
mysql -e "grant all privileges on *.* to 'root'@'localhost' identified by '123456';"
# 添加测试页面
ADD index.php /usr/share/nginx/html/index.php
# 分别开启80/443/9000/3306端口
EXPOSE 80
EXPOSE 443
EXPOSE 9000
EXPOSE 3306
# 复制脚本,设置权限,启动容器时启动该脚本
ADD run.sh /run.sh
RUN chmod 775 /run.sh
CMD ["run.sh"]

# 3. 编写执行脚本内容
$ vim run.sh
#!/bin/bash
/etc/init.d/nginx && /etc/init.d/php-fpm start && /usr/bin/mysqld_safe

# 4. 生成镜像
$ docker build -t centos:lnmp .

# 5. 启动容器并验证
$ docker run -d --name lnmp-test -P centos:lnmp

docker compose 多容器管理

docker compose 用于定义和运行多个容器的Docker应用的工具。Docker Compose 可以将Docker 对容器的所有部署、文件映射、容器连接等操作配置到 ".yml"配置文件中,通过Docker Compose 即可部署所有服务。

要实现Docker Compose,需要包括以下步骤:

1、将应用程序环境变量放在Docker文件中以公开访问。

2、在docker-compose.yml文件中提供和配置服务名称,以便它们可以在隔离的环境中一起运行。

3、运行docker-compose,启动并运行整个应用程序。

docker-compose安装:

$ yum -y install epel-release
$ yum -y install python-pip
$ pip --version
$ pip install docker-compose
$ docker-compose --version

docker compose 配置文件:

docker-compose命令和docker命令非常类似,但在使用docker-compose命令时,需要".yml"文件的配合才能完成。".yml"文件有三部分构成,分别为 version、services和networks。模板文件:

version:'2'
services:
  web:
  	image: dockercloud/hello-world
  	depends_on:
  	  - redis
  	ports:
  	  - 8080
  	networks:
  	  - front-tier
  	  - back-tier
  redis:
    image: redis
    links:
      - web
  	networks:
  	  - back-tier
  lb:
    image: dockercloud/haproxy
    ports:
      - 80:80
    links:
      - web
    networks:
      - front-tier
      - back-tier
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
   networks:
     font-tier:
       driver: bridge
     back-tier:
       driver: bridge
 

1. image:

image标签位于 services->web标签下,其中 web标签为用户自定义标签,用来设置服务名称。image标签指定服务的镜像名称或镜像ID。与docker命令类似,若本地不存在所指定的镜像,Compose会尝试从镜像仓库中拉取镜像。

2. build:

除了使用指定镜像外,还能通过Dockerfile文件构建一个新镜像,build标签就是用来指定Dockerfile所在文件路径的。build配置格式:

build:/path/to/build/dir  # 通过绝对路径设置
build:./dir  			  #通过相对路径指定
build:					  # 设定文件根目录,指定Dockerfile
  context:../
  dockerfile:path/of/Dockerfile

注意:同时使用了 image 和build ,docker compose 会将 image标签内容作为新镜像名称。

3. command:

command标签能够指定可以覆盖容器启动后默认执行的命令。配置格式:

command:bundle exec thin -p 3000

4. container_name:

该标签用于设置容器的名称。

5. depends_on:

该标签用于设置容器的依赖关系。

6. dns:

用于设置容器的DNS服务器,

7. tmpfs:

标签将Docker宿主机中的目录临时挂载到容器内。配置格式:

tmpfs: /run
tmpfs:
  - /run
  - /tmp

8. expose:

标签的功能与Dockerfile文件中 EXPOSE指令功能一致,用于设置暴露的端口,但不映射到宿主机。

expose:
 - "3000"
 - "8000"

9. extra_hosts:

类似 Docker 中的 --add-host 参数,指定额外的 host 名称映射信息,会向 "/etc/hosts"文件中添加一条记录。

extra_hosts:
  - "dockerhub:52.1.157.61"

10. ports:

用于设置端口映射,格式为:HOST:CONTAINER,或只设置容器端口,然后将主机的端口随机映射到容器中。

ports:
  - "3000"
  - "8000:8000"
  - "172.16.16.32:8001:8001"

11. volumes:

用于将一个目录或数据卷挂载到容器中,格式:[HOST:CONTAINER]

volumes:
  # 指定一个路径,Docker会自动创建数据卷
  - /var/lib/mysql
  # 使用绝对路径挂载数据卷
  - /opt/data:/var/lib/mysql

12. networks:

用于指定容器的网络类型,与Docker中的网络类型一致。

docker 镜像的构建原理和方式

https://blog.csdn.net/inthat/article/details/124060033

构建一个Docker镜像,最常用的有两种:

  • 通过docker commit 命令,基于一个已存在的容器构建出镜像。
  • 编写Dockerfile文件,并使用 docker build 命令来构建镜像。

上面这两种方法中,镜像构建的底层原理是相同的,都是通过下面的3个步骤来构建镜像:

1、基于原镜像,启动一个docker 容器。

2、在容器中进行一些操作,例如执行命令、安装文件等。由这些操作产生的文件变更都会被记录在容器的存储层中。

3、将容器存储层的变更 commit 到新的镜像层中,并添加到原镜像上。

在实际开发中,使用Dockerfile 来构建是最常用的,也最标准的镜像构建方法。

使用 Dockerfile 构建镜像,本质上也是通过镜像创建容器,并在容器中执行相应的指令,然后停止容器,提交存储层的文件变更。和用 docker commit 构建镜像方式相比,有三个好处:

  • Dockerfile 包含了镜像制作的完整操作流程,其他开发者可以通过 Dockerfile 了解并复现制作过程。
  • Dockerfile 中的每一条指令都会创建新的镜像层,这些镜像可以被 Docker Daemon 缓存。再次制作镜像时, Docker会尽量复用缓存的镜像层(using cache),而不是重新逐层构建,这样可以节省时间和磁盘空间。
  • 把这一切都放到一个 Dockerfile 里,既没有源码泄露,又不需要用脚本去跨平台编译,还获得了最小的镜像。

在实际生产环境中,标准的做法是通过 Dockerfile 来构建镜像。使用 Dockerfile 构建镜像,就需要编写Dockerfile文件。

Dockerfile快速开始

Dockerfile 通过读取Dockerfile中的指令自动生成映像。

  • dockerfile 是自定义镜像的一套规则
  • dockerfile有多条指令构成,Dockerfile中的每一条指令都会对应于Docker镜像中的每一层。

docker build 命令用于从 Dockerfile 构建映像。可以在 docker build命令中使用 -f 指向文件系统中任何位置的 Dockerfile。

docker build 命令会读取 Dockerfile 的内容,并将 Dockerfile的内容发送给 Docker 引擎,最终 Docker 引擎会解析Dockerfile中的每一条指令,构建出需要的镜像。

Dockerfile的基本结构

分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令,#为 Dockerfile 中的注释。

Dockerfile常用指令

Docker以从上到下的顺序运行Dockerfile 的指令。为了指定基本映像,第一条指令必须是FROM。一个声明以 #字符开头则被视为注释。

FROM命令:
FROM [--platform=<platform>] <image> [AS <name>]
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
  • FROM:指定基础镜像,必须为第一个命令

  • FROM指令用于指定基础镜像,ARG是唯一可以位于FROM指令之前的指令,一般用于声明基础镜像的版本。

  • --platform 选项可用在FROM多平台镜像的情况下指定平台。eg:linux/amd64、windows/amd64。

  • AS name 表示构建阶段命令,在后续FROM和COPY --from=name 说明中可以使用这个名词,引用此阶段构建的映像。

  • tag或digest值是可选的。如果你省略其中任何一个,构建器默认使用latest标签。如果找不到指定tag,构建器将返回错误。

    ARG CODE_VERSION=latest
    FROM base:${CODE_VERSION}
    CMD /code/run-app
    FROM extras:${CODE_VERSION}
    CMD /code/run-extras
    
LABEL

LABEL 指令将元数据添加到镜像。LABEL是键值对。要在LABEL值中包含空格,请像在命令行中一样使用引号和反斜杠。镜像描述信息。

注:LABEL 会继承基础镜像的LABEL,如遇到key相同,则值覆盖。

ENV

用于为镜像定义所需的环境变量,可以被Dockerfile文件中的其他命令调用(ENV、ADD、COPY、RUN、CMD)

ENV key=value
调用格式:
$variable_name 或者 ${variable_name}
WORKDIR

用来指定当前工作目录(或者称为当前目录),用于为Dockerfile中所有的RUN、CMD、ENTRYPOINT、COPY、ADD指定设定工作目录。

当使用相对目录的情况下,采用上一个WORKDIR指定的目录作为基准

相当于cd命令,但不同的是指定WORKDIR后,容器启动时执行的命令会在该目录下执行

VOLUME

可实现挂载功能,可以将宿主机目录挂载到容器中。

数据卷,用于在 image 中创建挂载点目录,以挂载 Docker host 上的卷或者其他容器上的卷。

VOLUME mount_point
VOLUME ["mount_point1","mount_point2"]

如果挂载点目录下有文件存在,docker run 命令会在卷挂载完成后将所有文件复制到容器中。

RUN

RUN主要用于在 Image里面执行指令,比如安装软件,下载文件等。

是 docker build 镜像构建的时候需要执行的 shell命令,默认 “/bin/sh -c”运行。

RUN在镜像构建完成之后运行结束。

RUN执行的命令只能基于基础镜像的命令,执行之前先要确定基础镜像是否有该命令。

RUN command1 && command2
RUN ["executable","param1","param2"]
- executable 为要运行的命令
- param1为命令的参数

CMD

启动容器指定默认要运行的程序或命令,默认"/bin/sh -c" 运行。

Dockerfile只允许使用一次CMD命令。使用多个CMD会抵消之前的所有命令,只有最后一个命令生效。一般来说,这是整个Dockerfile脚本的最后一个命令。

FROM ubuntu
CMD ["/usr/bin/wc","--help"]

CMD有三种形式:

  • CMD ["exec","param1","param2"]:使用exec执行,推荐方式。
  • CMD command param1 param2:在/bin/sh中执行,可以提供交互操作。
  • CMD ["param1","param2"]:提供给ENTRYPOINT的默认参数(极少这样使用)。

注意:不要把RUN和CMD搞混了

RUN是构建容器时就运行的命令以及提交运行结果。

CMD是容器启动时执行的命令,在构建时并不运行。

COPY

编写Dockerfile的时候 copy 宿主机文件到镜像中。

COPY指令复制文件、目录到镜像文件系统。

ADD:

类似于COPY指令,ADD支持 tar 文件和 URL 路径。

使用ADD命令会将压缩包解压到容器中。COPY指令不会解压 .tar压缩包。

ADD <src> ... <dest>
ADD ["<src>"... "<dest>"]

ADD注意事项:

  • src为一个目录的时候,会自动把目录下的文件复制过去,目录本身不会复制
  • src为多个文件,dest必须是一个目录
USER

设置启动容器的用户,可以是用户名或UID

USER daemon
USER UID

注意:如果设置了容器以daemon用户去运行,那么RUN、CMD和ENTRYPOINT都会以这个用户去运行,使用这个命令一定要确认容器中拥有这个用户,并且拥有足够权限。

EXPOSE

EXPOSE指令为容器打开指定的监听端口以实现与外部通信,可以指定TCP或UDP,如果不指定协议,默认为TCP端口。但是为了安全,docker run 命令如果没带上相应的端口映射参数,Docker并不会将端口映射出去。

EXPOSE 80/tcp
EXPOSE 80/udp

注:不会直接对外暴露这里的端口,只有在run的时候加上 -P(大写)才会将EXPOSE的端口暴露出去。

指定映射端口方式:

docker run -P:将所有端口发布到主机接口,每个公开端口绑定到主机的随机端口,端口范围在/proc/sys/net/ipv4/ip_local_port_range定义的临时端口范围内。

docker run -p:显示映射单个端口或端口范围。

ENTRYPOINT

ENTRYPOINT 指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所有其他传入值作为该命令的参数。

一个Dockerfile中只能有一个ENTRYPOINT命令。如果有多条,只有最后一条有效。

无参的方式:

ENTRYPOINT ["/usr/sbin/nginx"]

指定参数的方式:

ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off"]

dock run 的 --entrypoint 标志可以覆盖原Dockerfile中的ENTRYPOINT指令。

注意:该命令是指定你每次 docker run 启动容器的时候,都会自己执行的一个程序!!!

CMD 与 ENTRYPOINT的关系:

  • CMD可以为ENTRYPOINT提供参数,ENTRYPINT本身也可以包含参数,但是可以把需要变动的参数写到CMD里面,而不需要变动的参数写到 ENTRYPONT里面。

  • ENTRYPOINT 使用第二种shell方式会屏蔽掉CMD里面的命令参数和docker run后面加的命令。

  • 在Dockerfile中,ENTRYPOINT指定的参数比运行docker run时指定的参数更靠前。

    ENTRYPOINT/CMD 最后一条命令为无限运行的命令:

    这句话才是使用ENTRYPOINT的精髓。

    在Docker Daemon 模式下,entrypoint、cmd 命令的最后一个命令,一定是当前容器需要一直运行的,才能防止容器退出。

    当指定了ENTRYPOINT 后,CMD的含义就发生了改变,不再是直接的运行其命令,而是将CMD的内容作为参数传给 ENTRYPOINT 指令。换句话说实际执行时,会变成 “ ”

工作中常用技巧总结:

Dockerfile 中使用变量:

通过关键字ARG,ENV设置变量

ARG arg1=test
ENV env1=production

注意:

  • 不能通过表达 如$(uname -a) 进行设置,只能设置为常量。
  • ARG 设置的变量在构建完成后,就会丢失。即在Docker中无法引用该变量。
  • ENV 设置的变量在Docker中可以通过 eg: ${env1}访问。

在RUN中设置变量

在RUN中通过 arg=someValue中设置变量,以下脚本先获取Debain的系统版本号,并设置到 os_release变量中,在后续的命令中可以通过 ${os_release}进行引用。

RUN os_release="$(cat /etc/os_relase) | grep VERSION_CODENAME | awk -F '=' '{print $2}'" && \
echo "deb http://mirrors.aliyun.com/debian/${os_release} main non-free contrib\n\ 
deb http://mirrors.aliyun.com/debian-security ${os_release}/updates main\n\
deb http://mirrors.aliyun.com/debian/${os_release}-updates main non-free contrib\n\
deb http://mirrors.aliyun.com/debian/${os_release}-backports main non-free contrib\n"\
> /etc/apt/sources.list

一个RUN命令,相当于新打开一个shell。所以上一个RUN设置的变量无法在下一个RUN中使用。

因此如果你需要在build期间使用某些变量,那么ARG是最好的选择。如果你是想在运行期间使用,那么ENV是唯一的选择。

ENV主要是定义环境变量,在docker run 的时候ENV 的配置会加载到容器内部,但ARG的参数在内部是没法看到的。同时也可以通过下面命令更改ENV的默认值:

docker run -e var=yyy

如果想在BUILD的时候,改变我的环境变量,而不是每次RUN的时候更改,需要怎么做?

ARG和ENV两者结合使用

ARG var
ENV var=${var}

这样既可以在build的时候通过docker build --build-arg var=xxx来传递参数,也可以在运行的时候通过 docker run -e var=yyy来传递参数。

eg:

docker build --build-arg INSTALL_ZIP=myinstall.zip -t centos-test:v4 .

ARG INSTALL_ZIP
COPY ./${INSTALL_ZIP} /root/
RUN chmod 755 ${INSTALL_ZIP}
RUN unzip ${INSTALL_ZIP}

在Dockerfile中使用变量的方式:

  • $varname

  • $

  • $

  • $

    第一种和第二种相同

    第三种表示当变量不存在使用 - 号后面的值

    第四种表示当变量存在时使用 + 号后面的值(当然不存在也是使用后面的值)

制作docker 镜像

docker build 命令制作docker 镜像

docker build 命令用于使用Dockerfile创建镜像。

docker build [OPTIONS] PATH | URL | -

OPTIONS说明:

  • --build-arg=[]:设置镜像创建时的变量
  • --cpu-shares:设置cpu使用权重
  • --cpu-period:限制cpu CFS周期
  • --cpu-quota:限制CPU CFS配额
  • --cpuset-cpus:指定使用的CPU id
  • --cpuset-mems:指定使用的内存 id
  • --disable-content-trust:忽略校验,默认开启
  • -f:指定要使用的Dockerfile路径
  • --force-rm:设置镜像过程中删除中间容器
  • --isolation:使用容器隔离技术
  • --label=[]:设置镜像使用的元数据
  • --m:设置内存最大值
  • --pull:尝试去更新镜像的新版本
  • --quiet,-q:安静模式,成功后只输出镜像ID
  • --rm:设置镜像成功后删除中间容器
  • tag, -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签

忽略文件:.dockerignore

指定文件:docker build -f

添加标签:docker build -t

不使用缓存:docker build --no-cache

--file ,-f Dockerfile的完整路径,默认值为 'PATH/Dockerfile'

--tag -t 镜像的名字及tag,通常 name:tag或者name格式,可以在一次构建中为一个镜像设置多个tag

PATH|URL :给出命令执行的上下文。上下文可以是构建执行所在的本地路径PATH,也可以是远程URL,如:git库。

docker build -f docker/Dockerfile -t myapp_debug .

使用当前目录的Dockerfile创建镜像,标签位 runoob/ubuntu:v1

docker build -t runoob/ubuntu:v1 .

也可以通过 -f Dockerfile文件的位置:

docker build -f /path/to/a/Dockerfile .
制作镜像:
docker build -t jm/stable_image_new_v3 .
运行:
docker run -itd -p 172.16.61.99:80:80 -p 172.16.61.99:443:443 -p 172.16.61.99:10022:22 -v /home/webroot/static/webimg:/data/webroot/static/webimg -v /home/goweb/src/DockerAutoPublish/startsh:/home/goweb/src/DockerAutoPublish/startsh -v /home/php_vendor:/data/php_vendor -v /home/sh:/data/sh -e START_PATH=/home/goweb/src/DockerAutoPublish/startsh/172.16.61.99_start.sh --name=test jm/stable_image_new_v3

原理:

docker 在运行时分为Docker引擎(服务端守护进程)以及客户端工具,我们日常使用各种docker命令,其实就是在使用客户端工具与docker引擎进行交互。

那么当我们使用 docker build 命令构建镜像时,这个构建过程其实是在docker引擎中完成的,而不是在本机环境。

那么如果在Dockerfile中使用一些COPY等指令来操作文件,如何让Docker引擎获取到这些文件呢?

这里有一个 镜像构建上下文 的概念,当构建的时候,由用户指定构建镜像的上下文路径,而 docker build 会将这个路径下所有的文件都打包上传到Docker引擎,引擎内将这些内容展开后,就能获取到所有指定上下文中的文件了。

比如:dockerfile中 COPY ./package.json /project ,其实拷贝的并不是本机目录下的package.json文件,而是 docker引擎中展开的构建上下文中的文件,所以如果拷贝的文件超出了构建上下文的范围,Docker 引擎是找不到那些文件的。

docker build 最后的 .号,其实是在指定镜像构建过程中的上下文环境的目录。

COPY 文件的问题:

最简单的方案是,将所有涉及到的文件或者文件夹与Dockerfile放在同一个目录下,这样COPY命令就能找到文件或者目录了。

需要注意的是,在 docker build 命令接收的参数中,提供给 docker build 命令的 -f 选项应该 Dockerfile 路径名。如果 Dockerfile 文件就叫 Dockerfile 那么文件名可省略,如果 Dockerfile 文件就在当前目录下,那么 -f 选项可省略。

docker build -f ./Dockerfile -t xxx .
# 等同于
docker build -f . -t xxx .
# 等同于
docker build -t xxx .

如果你的 Dockerfile 在别处,而且还不叫 Dockerfile 那么你的 docker build 命令就应该形如如下形式:

docker build -f /xxx/yyy/zzz -t xxx .

在上面的例子中,你的 Dockerfile 在 /xxx/yyy 下,名为 zzz

posted @ 2024-01-19 15:36  caibaotimes  阅读(158)  评论(0)    收藏  举报