前言
一、基本概念
1、Docker镜像
镜像就是一个文件,例如我们的应用镜像、环境镜像(例如nginx、mysql等),镜像是创建Docker容器的基础。
2、Docker容器
Docker容器类似于一个沙箱(例如做支付的时候的支付宝的沙箱),Docker通过容器来运行和隔离应用。容器是从镜像创建的应用实例,可以启动、停止、删除,这些容器彼此相互隔离,互不打扰,可以将每个容器都看作一个单独的Linux系统。
3、Docker仓库
类似于我们的代码仓库,它是集中存放镜像文件的地方。我们可以将自己的Docker镜像上传到我们的Docker仓库,同时也可以从Docker仓库下载我们需要的镜像。最大的公开仓库就是官方仓库https://hub.docker.com/
二、centos7安装Docker
Docker要求CentOS系统内核高于3.10,uname -r
查看当前的内核版本
如果之前安装过Docker,可以执行下列命令清除,注意,切换到root执行
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
先查看当前的yum源,yum repolist
,如下
设置yum源,并更新 yum 的包索引
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum makecache fast
安装Dockeryum install docker-ce docker-ce-cli containerd.io
,安装过程中需要输入3次“y”确认安装,安装成功如下所示
启动Dockersystemctl start docker
,设置为开机启动systemctl enable docker
,然后输入docker version
检查是否启动成功,若给出版本号,则成功
然后我们运行一下经典的hello world
,输入docker run hello-world
,可以看到如下信息
三、常用的Docker命令
命令 | 备注 |
---|---|
docker images | 镜像列表 |
docker pull | 拉取镜像 |
docker search | 搜索镜像 |
docker push | 上传镜像 |
docker ps | 容器列表 |
docker create | 创建容器 |
docker run | 只在第一次运行时使用,将镜像放到容器中(docker cearte),以后再次启动容器只需要docker start,参数说明:-d后台运行容器,并返回容器ID、-i交互式运行、–memory限制容器可用内存、–memory-swap设置swap区可用内存,默认和–memory一样,必须≥memory、–name容器名字、–net容器运行网络、–ip指定容器ip、-P随机映射端口、-p本地端口:容器端口,将容器某个端口映射到本地端口上 |
docker start | 启动已存在的容器,需要知道容器ID或名称 |
docker restart | 重启容器 |
docker logs | 容器运行日志 |
docker stop | 停止容器,优雅停机 |
docker kill | 杀死容器 |
docker exec | 在使用-d参数运行容器时,容器启动后会进入后台,此时想要进入容器,可以通过这个指令进入,推荐大家使用dockerexec命令,因为使用它在退出容器终端,不会导致容器的停止 |
docker rm xxx | 移除容器 |
docker rename xxx | 重命名 |
上述命令 --help | 查看任意命令的参数、作用等 |
四、运行Nginx
1、拉取镜像
由于从docker的官方镜像仓库下载太慢,因此这里使用https://c.163yun.com/hub#/library/repository/version?repoId=3181
网易的镜像中心,找到nginx
直接从右上角复制,执行shell命令docker pull hub.c.163.com/library/nginx:latest
,然后查看镜像
2、启动容器
先通过docker run
命令启动,docker run hub.c.163.com/library/nginx:latest
,然后查看运行的容器
ctrl+c终止运行,然后再尝试后台运行docker run -d hub.c.163.com/library/nginx
然后用docker exec -it id bash
命令进入容器内部,并通过which nginx
命令查看nginx的位置
3、本机访问Nginx
我们从上面可以看到nginx在虚拟机上是80端口,那么我们本地怎么访问呢?也是用80端口吗?尝试一下
显然是不行的,这是因为我们启动nginx的时候,并没有指定主机的端口,在第三节常用命令中,指定端口有两种方式,-P随机端口,-p指定端口,我们分别尝试一下,先停掉当前的nginx,通过docker stop id
优雅方式停止,然后docker run -d -P hub.c.163.com/library/nginx
,再查看运行的容器
发现给我们随机的端口是49153,我们访问一下,发现成功了
我们再尝试一下指定端口,毕竟随机的端口不容易记住,还是先停止容器,然后执行docker run -d -p 8080:80 hub.c.163.com/library/nginx
,然后我们本机访问8080端口,也是成功的
五、Docker网络
Docker默认提供了三种网络模式,在生成容器时,如果不指定网络模式默认使用bridge桥接模式,我们先看下这三种网络模式docker network ls
先说none模式,这个看上去就是容器没有进行任何网络配置,即这个容器没有网卡、IP等信息,但是它是有自己的Network Namespace,因此这种网络类型不能联网,可以很好的保证容器的安全性;
然后是host模式,这种模式容器没有自己的Network Namespace,和宿主机共用一个,并且使用宿主机的IP和端口;
最后是默认的bridge(桥接)模式,我们先看下没有安装docker的机器上的网络设置,只有ens33、lo、和virbr0这三个配置
然后,我们看看启动一个容器之后,本机的网络,发现多了一个docker0的配置
这个docker0就是默认的虚拟网桥,新建的容器会自动桥接到该接口下,附加在其上的任何网卡之间都能自动转发数据包,创建一对虚拟设备接口 veth pair,将其中一个接口设置为容器的 eth0接口(容器网卡),另一个接口放置在宿主机命名空间中,以 vethxxx 这样的名字命名,宿主机上的所有容器都连接到这个内部网络上,分配一个和网桥 docker0在同网段的IP地址给容器,并设置docker0的IP地址为容器的默认网关,如图所示
可以看一下启动的容器bb0d…的网络设置
然后再看下网桥的设置docker network inspect bridge
[
{
"Name": "bridge",
"Id": "6b8a1209420f33468d60b9853eceb922724a517c5164738b1666edb2eaaade72",
"Created": "2022-10-27T02:40:17.103940791-07:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"bb0d08a1a2a33354c5d616f1148e50dc9d4b88589148d71fcb2965640c12cb9f": {
"Name": "frosty_swirles",
"EndpointID": "ed0de88801c1eef44fcbb751f7d20107577036f61b62b2eedff4503b7725ad2e",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
可以看到,在网桥设置中,将我们的容器包含进去了,也就是说容器和网桥docker0建立了连接。
六、Dockerfile
Dockerfile是由一行行命令语句组成,一般分为四部分:基础镜像信息、维护者信息、镜像操作指令、容器启动时执行指令。
1、自定义Dockerfile构建镜像
我们在空目录新建一个Dockerfile文件,输入如下内容
FROM hub.c.163.com/library/nginx
RUN echo '这是雅俗共赏构建的nginx镜像' > /usr/local/share/index.html
FROM:定制的镜像是基于FROM的镜像,这里的nginx就是基础镜像
RUN:用于执行后面的命令行命令
然后开始构建镜像,在Dockerfile文件的存放目录下,执行构建命令:docker build -t nginx:ysgs .
nginx:ysgs(镜像名称:镜像标签),最后的.代表本次执行的上下文路径
至此,我们的镜像构建成功!
2、Dockerfile指令
COPY:复制指令,从上下文目录中复制文件或目录到容器的指定路径,COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
ADD:和COPY指令使用类似,功能也类似,同样需求下,官方推荐使用COPY
CMD:类似RUN指令,用于运行程序,但是二者的运行时间点不同,CMD在docker run时执行,RUN在docker build时执行CMD ["<可执行文件或命令>","<param1>","<param2>",...]
ENTRYPOINT:类似CMD命令,但是不会被docker run的命令行参数指定的指令覆盖,而且这些参数会被当做参数传给ENTRYPOINT指令指定的程序,但是如果docker run使用了–entrypoint选项,会覆盖指令,可以搭配CMD指令使用,一般是变参才会使用CMD,这里的CMD是给ENTRYPOINT传参
FROM nginx
ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参
如果不传参,docker run nginx:test
,容器内默认运行nginx -c /etc/nginx/nginx.conf
;如果传参docker run nginx:test -c /etc/nginx/new.conf
,容器内运行nginx -c /etc/nginx/new.conf
ENV:设置环境变量,ENV <key> <value>
ARG:构建参数,和ENV作用一致,作用域不同,ARG只在dockerfile构建过程中有效,构建好的镜像不存在此环境变量
VOLUME:定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷,VOLUME ["<路径1>", "<路径2>"...]
EXPOSE:声名端口,EXPOSE <端口1> [<端口2>...]
WORKDIR:指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在,WORKDIR <工作目录路径>
USER:指定执行后续命令的用户和用户组,USER <用户名>[:<用户组>]
HEALTHCHECK:用于指定某个程序或者指令来监控 docker 容器服务的运行状态
ONBUILD:用于延迟构建命令的执行,本次构建其指定的指令不执行,当有其他Dockerfile使用之后,才执行,ONBUILD <其它指令>
LABEL:用于给镜像添加一些元数据,LABEL <key>=<value> <key>=<value> <key>=<value> ...,例如添加作者信息 LABEL author:"ysgs"
总结
至此,Docker的一些基本操作就已经完成了,这些只是入门级的知识,要想更加深入的掌握和运用Docker,还需要参照官网,学习更多的内容。