码头工人
一、 docker配置文件
1 、docker默认的配置文件/etc/docker/daemon.json。
2、docker加速
-
docker cn
-
阿里云加速器
-
中国科技大学加速器
- 为了永久性保留更改,您可以修改 /etc/docker/daemon.json 文件并添加上 registry-mirrors 值。如下
{ "registry-mirrors": ["http://hub-mirror.c.163.com"] }
使用systemctl restart docker重启docker,使docker重新加载配置文件
二、docker常用命令
- docker version 查看docker服务端版本以及客户端版本
- docker info 查看docker详细信息,比如已经启动了多个镜像,有多少容器
- docker image list 查看本地已经拉下来的镜像
- docker image pull nginx:1.14-alpine 拉取某一个指定的镜像
- docker image rm 83aa35aa1c79 删除本地镜像
- docker network list 查看网络
- docker container list 显示容器,docker container list -a 查看隐藏容器
- docker container run --name box -it busybox 运行一个容器, i交互, t 给一个终端,-d 在后台分离运行容器并打印容器ID,docker run --name n1 --rm nginx:v1.1.1 cat /docker/web/html/index.html, 运行时可以指定命令,命令一结束,容器就停止。-f 运行在前台
- docker container start -ia box a附加, i交互, 附加交互,如果是后台守护进程可以直接启动,不用附件交互
- docker container stop box 停止容器,相当于发15信号
- docker container kill box 停止容器,相当于发9信号
- docker container rm box 删除容器
-
docker container exec container_name command 指明在什么容器执行什么命令 ps. docker container exec -it box /bin/sh
- docker container logs box 一般一个容器只运行一个主进程, 所以log没有必要保存,直接实时获取
- docker build -t nginx:v1.1.1 ./ 制作镜像
- docker logs name 查看实时日志
三、 docker镜像
docker 镜像含有启动容器所需要的文件系统以及其内容,因此其用于创建并且启动docker容器,
1、构建镜像的方法
docker build
docker commit
docker commit -p box,-p,暂停状态,防止丢数据,将容器做成镜像 -c 默认运行的命令
docker tag 58821e6fb52d liuwenfan/box:v1.1 给现有的镜像打上标签, 可以打多次标签
我自己使用阿里云镜像仓库,
配置一下阿里云镜像
{ "registry-mirrors": ["your address"] }
1 docker login --username=176xx576201 registry.cn-hangzhou.aliyuncs.com
2 docker tag 58821e6fb52d registry.cn-hangzhou.aliyuncs.com/liuwf/sail:v1.0 重新打标签,修改仓库名字,必须修改地址名仓库名名称空间和远程仓库一直才可以push
3 docker push registry.cn-hangzhou.aliyuncs.com/liuwf/sail/haha
执行之后,见下图
更加详细操作登录阿里云镜像仓库-管理
镜像的导入和导出
docker save -o mydocker.gz 58821e6fb52d 83aa35aa1c79 将镜像打包为本地文件
docker load -i mydocker.gz 导入镜像
三、docker网络
- docker run --name t2 -it --rm busybox:latest 这样默认创建的容器是有自己的eth0地址
- docker run --name t2 -it --rm --network bridge busybox:latest 指定网络,默认就是bridge
- docker run --name t2 -it --rm --network none busybox:latest,使用ifconfig查看,没有创建网络
- docker run --name t2 -it --network bridge -h liuwenfan --rm busybox:latest, 创建容器的同时注入主机名
- docker run --name t2 -it --network bridge -h liuwenfan --dns 114.114.114.114 --rm busybox:latest,创建容器是注入dns
见以下
暴露端口
使用-p选项暴露端口
1、 -p <containerPort> , 将指定的容器端口映射至主机所有地址的的一个动态端口范围在30000-32767之间
使用这个命令创建一个nginx容器, 将nginx容器80端口暴露在宿主机的一个随机端口上
docker run --name t3 -it --network bridge -p 80 --rm nginx
使用docker container list (或者 docker port t3 查看容器端口转发情况 )查看容器,见下图
可以看到, 将nginx容器的80端口暴露在了宿主机的32770端口上, 接下来使用curl localhost:32770,见下图
在外部访问, 见下图
2、 转发到宿主机固定地址
-p <hostPort> : <containerPort>
使用docker run --name t4 -p 80:80 --rm -it nginx,创建容器, 将容器80端口转发至宿主机80端口, 通过curl 访问本机见下图
通过外部访问见下图
使用docker port t4查看容器端口转发情况
3、 将指定端口映射在主机指定<ip> 的动态端口
使用docker run --name t3 -it --network bridge -p 192.168.254.142::80 nginx创建容器,使用docker port t3查看容器使用端口转发情况,见下图
外部访问见下图
内部使用localhost进行访问,见下图
4、 将容器的端口映射到宿主机指定的ip以及指定的端口
-p <ip>:<hostPort>:<containerPort>
访问效果不再描述,肯定没有问题
注意: -p 选项可以使用多次, 比如一个web服务既要暴露80端口, 也要暴露443端口, -P(大写p), 可以直接一次行暴露所有端口, 不用指定端口
共享网络空间
使用ocker run --name b6 -it --rm busybox 创建一个容器, 查看ip地址
使用docker run --name b3 -it --rm busybox 创建另一个容器, 查看ip地址
接下来把b3停掉, 使用 docker run --name b3 --network container:b6 --rm -it busybox创建一个新的b3,查看地址
可以看到, 现在b3是和b6共用一个IP地址, 但是文件系统什么的还是隔离的,
使用docker run --name b3 --rm -it --network host busybox 容器与宿主机共享网络空间
以上图, 现在是容器和宿主机共享一个网络空间,启动服务之后, 直接在外部可以访问
四 、Docker 存储卷
docker 存储数据存在的问题
1、 存在联合文件系统中, 不易于宿主机访问,
2、 容器之间是数据共享不方便
3、 删除容器数据会丢失
将容器中的某一个目录与宿主机的中某一个目录进行绑定,其一 这样可以避免容器被销毁之后数据也被销售,数据持久,生命周期脱离容器, 其二, 读写效率
个人理解, 有点像vmware 和pc的共享文件夹,仔细一想, 也不想, 不过如果理解不了可以先大概这么理解一下。可以把卷和共享文件系统绑定, 可以直接脱离单个服务器,形成集群。
docker有两种存储卷
1、绑定挂载卷, 就是宿主机指定特定路径,容器也指定特定路径, 然后二者建立关联关系
使用docker run --name b4 -it -v /data busybox 创建一个容器, ls查看目录效果如下, 在创建容器时自动创建了/data目录
新开一个shell, 使用docker inspect b4 |grep -A 10 Mounts 查看挂载点详细信息,见下图
然后 cd /var/lib/docker/volumes/9ad47aca135e9037a81a38b04503cac96dabd31d15d112a7b668cf2ae81404b7/_data中, mkdir test,cd test, vim test.sh 输入hello world, wq保存退出,然后进入容器内部的data目录下, 查看刚才新建的文件,见下图
2 、docker管理卷 只需要在容器内指定容器的挂载点, 宿主机不需要管,由容器自行创建或者找一个目录
例如: docker run --name b5 --rm -it -v /data:/data busybox
宿主机文件查看如下图
查看挂载点详情见下图
其他不再描述, 和绑定卷一致
两个容器如果绑定宿主机的目录是同一个目录, 这样可以在容器之间共享数据
可以启动一个基础容器,指定它的挂载点,都不用启动它, 只要不删除,其他的容器都复制它的存储卷
例如:docker run --name server -it --rm -v /data/:/data/ centos 创建一个基础容器, 然后 docker run --name b8 --rm -it --volumes-from server busybox, 这样, 新建的容器就会和server容器共用一个文件夹,根据这个思路, 以后创建新容器时只要用--volumes-from 选项容器就行,不用每一次创建新的容器都指定新的挂载点。
记住以上的思路就行了, 有专门的基础镜像以供使用, 不用专门下载centos镜像。
五、Dockerfile
- Fromat
- #Comment
- INSTR UCTION arg 不区分大小写, 但是约定俗成大写,自上而下,依次执行,文件名首字母必须大写。
1 、FROM 指令是最重要的一个, 且必须为Dockerfile文件开篇的的第一个非注释行,用于为映像文件构建过程中指定基准镜像,后续的指令运行与此基准镜像提供的环境
2 、MAINTANIER 镜像提供者, 已经废弃, 可以用LABEL代替
3、LABEL 为镜像指定各种元数据
4、 COPY 用于从docker主机复制文件至创建的新镜像文件,注意, 不复制本目录
5、ADD add指令类似于copy指令,add支持使用tar文件和url路径,tar包会自动展开为目录
6、 WORKDIR 用于为dockerfile所有的 RUN ADD COPY ENTRYPOINT CMD 指定设定工作目录
7、VOLUME 勇于在镜像中创建一个挂载点或者目录,以挂载Docker host 上的卷或者其他容器上的卷
8、EXPOSE 用于为容器打开指定要监听的端口已实现和外部通信(-P,暴露所有要暴露的端口),文件中写了不一定会暴露, 加上大写-P, 待暴露,默认暴露
9、 ENV 用于为镜像定义所需要的的环境变量,并且可以被Dockerfile 文件中位于其后的其他指令(如 ENV ADD COPY等)所调用
docker run --name n2 -e base_name="liuwf" --rm nginx:v1.20 printenv可以动态注入env,效果见下图
10、RUN 用于指定docker build 过程中运行的指令,其可以是任何命令,其执行过程在docker bulid 过程中执行
#这是一段测试代码 FROM busybox:latest MAINTAINER "m17600576201@163.com" LABEL maintainer="m17600576201@163.com" COPY index.html /docker/web/html/ COPY yum.repos.d /docker/etc/yum.repos.d/ #ADD http://nginx.org/download/nginx-1.16.1.tar.gz /docker/ #远程下载的tar包不会被展示 ADD https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1586719761009&di=b0e4ba860268435b0d6e8fa64175f0e6&imgtype=0&src=http%3A%2F%2Fbbs.jooyoo.net%2Fattachment%2FMon_0905%2F24_65548_2835f8eaa933ff6.jpg /docker/img/ ADD test.tar /dokcer/tar/ WORKDIR /docker/ ADD test.tar ./ VOLUME /data/mysql/ EXPOSE 80/tcp ENV ROOT /gen/ #ENV ROOT=/data/ \ # haha=/data1/ # 以上用于一次性定义多个环境变量 COPY index.html ${ROOT:-/gen/} RUN cd /docker/web/html && \ mv index.html haha.html && \ echo "update success"
11、CMD 运行的过程中发生在docker run中, 只有最后一个CMD生效,注意, 如果这儿是以json格式写的命令, 那么是不会启动为shell的子命令的
FROM busybox LABEL maintainer="afan6201@126.com" name="liuwf" ENV ROOT="/data/html/" RUN mkdir -p ${ROOT} && \ echo "hello world" > ${ROOT}/index.html CMD /bin/httpd -h ${ROOT} -f
12、 ENTRYPOINT 类似CMD指令的功能,用于为容器指定默认运行程序,从而使容器像是一个单独的可执行程序,与CMD命令不同的是,由ENTRYPOINT启动的成功程序不会被docker run命令行指定的参数所覆盖,而且, 这些命令行参数会被当做参数传递给ENTRYPOINT 指定的程序
FROM busybox LABEL maintainer="afan6201@126.com" name="liuwf" ENV ROOT="/data/html/" RUN mkdir -p ${ROOT} && \ echo "hello world" > ${ROOT}/index.html ENTRYPOINT /bin/httpd -h ${ROOT} -f
cmd作为参数
FROM busybox LABEL maintainer="afan6201@126.com" name="liuwf" ENV ROOT="/data/html/" RUN mkdir -p ${ROOT} && \ echo "hello world" > ${ROOT}/index.html CMD ["/bin/httpd", "-f", "-h ${ROOT}"] #CMD这种格式是把CMD作为参数传递给entrypoint ENTRYPOINT ["/bin/sh","-c"]
docker run时 如果不加CMD 会把Dockerfile默认的CMD作为参数传递给ENTRYPOINT执行, 如果docker run 时指定了CMD, docker run 的CMD会覆盖Dockerfile的CMD, ENTRYPOINT此时会只执行docker run传递的参数
ENTRYPOINT和CMD的区别
nohup交给其他父进程,& 运行在后台
1 多数情况下, ENTRYPOINT指定一个shell, 指定一个父进程, CMD一般作为子进程
2 CMD作为参数传递给ENTRYPOINT
见以下
FROM nginx:1.14-alpine LABEL maintainer="afna6203@126.com" ENV nginx_root="/data/web/html/" ADD entrypoint.sh /bin/ ADD index.html ${nginx_root} CMD ["/usr/sbin/nginx", "-g", "daemon off;"] ENTRYPOINT ["/bin/entrypoint.sh"]
#!/bin/sh cat > /etc/nginx/conf.d/www.conf << EOF server{ server_name ${HOSTNAME}; listen ${IP:-0.0.0.0}:${PORT:-80}; root ${ngxin_root:-/usr/share/nginx/html}; } EOF exec "$@"
以上脚本有点问题, 原因没有找到, 不过就是举个例子,具体使用可以查看大神们写的
13、 USER 用于指定运行image时 运行指令时的用户名或者UID默认情况下, container运行身份为root用户
14、 HEALTHCHECK 检测容器健康状态
FROM nginx:1.14-alpine HEALTHCHECK --start-period=3s CMD wget -O - -q http:localhost:80/ EXPOSE 80/TCP
15、 SHELL 定义容器启动是默认的shell, 容器为win时亦可以选择win相关的
16、 STOPSIGNA 容器中pid为1的进程可以接受docker stop 信号停止主进程, 主进程停止, 容器关闭,这个用户修改信号, 一般不用改
17、 ARG 只在build中使用, 见以下
FROM nginx:1.14-alpine ARG name="liuwf" LABEL maintainer="${name}" EXPOSE 80/TCP
docker build --build-arg name="lww" -t nginx:v2.2 ./
docker image inspect nginx:v2.2|grep main
18、 ONBUILD 用于在Dockerfile定义一个触发器,其参数是任意一个Dockerfile 指令,自己构建时不会执行这个指令, 在别人基于此镜像构建自己的镜像时会执行,以下例子
FROM busybox
MAINTAINER hello
ONBUILD RUN mkdir mydir
FROM b1
RUN mkdir -p /opt/hahah/
以上是Dockerfile, 多读几个别人写的就自己会写了
六、Docker-Compose 容器编排工具 用来维护docker节点,它是一个用于定义和运行多容器 Docker 的应用程序工具
1、 安装Docker-Compose
curl -L https://github.com/docker/compose/releases/download/1.24.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose
使用docker-compose --version 验证是否安装成功
2、 docker-compose.yml的使用, 文件名固定, 结尾可以是用 .yml
或 .yaml
作为文件扩展名,必须是这个,docker-compose.yml包含version、services、networks3大部分
最基本的一个例子
version: '3' services: web: build: . ports: - "5000:5000" volumes: - .:/code environment: FLASK_ENV: development redis: image: "redis:alpine"
3、docker-compose基本命令
- docker-compose down 关闭容器删除
- docker-compose up 启动容器, 加-d启动到后台
- docker-compose ps
查看当前正在运行的内容:
- docker-compose run web env 运行一次性的命令
- docker-compose stop 停止容器
以上docker-compose原文见https://docs.docker.com/compose/gettingstarted/, 个人感觉就是用来管理docker的一个工具, 就像pm2用来管理node一样的东西。不用docker-compose也可以, 只不过是吧docker run 的命令和参数写在脚本里面统一管理。
以上写的都是基础中基础,有兴趣的话还要自己多去找资料。多练习。