首先,我们进行软件研发需要开发dev、线上prod两套环境,容易存在问题:
比如发布一个jar项目,但该jar的运行需要依赖Redis、ES、Hadoop等环境,也就是说部署该项目需要先安装以上几种环境,此时部署该项目就比较费时费力。如果能把这个项目与环境打包在一起部署,就会效率很多。
Docker给以上问题提供了解决方案,具体应用类似于打包Java程序为apk文件发布到应用商店,下次使用的时候在应用商店下载即可:
其思想来自于集装箱,将项目与环境打包装箱,每个箱子是互相隔离的,Docker通过隔离机制,可以将服务器资源利用到极致。
2010年,几个程序员在美国成立了一家名为dotCloud的公司,其旨在提供pass云计算服务(LXC有关的容器技术)。他们将自己的技术(容器化技术)命名为Docker,然而Docker刚刚诞生时并没有引起行业的关注。
2013年,dotCloud公司效益越发不景气,所以他们选择开源Docker技术。后来越来越多的人发现了Docker的优点,Docker火了,往后的每个月Docker都会更新一个新的版本。
2014年4月9日,Docker 1.0发布。
简言:十分轻巧。在容器技术现世之前,我们使用的是虚拟机技术(VM),在windows中安装一个Vmware,通过这个软件我们可以虚拟出来一台或多台电脑,比较笨重。虚拟机属于虚拟化技术,Docker容器技术也属于虚拟化技术。
Docker是基于Go语言开发的开源项目
官网地址:https://www.docker.com/
文档地址:https://docs.docker.com/
仓库地址:https://hub.docker.com/
在DevOps(开发、运维)方面
- 更快的交付和部署
传统的部署:一堆帮助文档、安装程序
Docker部署:一键运行打包镜像、发布测试- 更便捷的升级和扩缩容
Docker部署应用像搭积木一样。比如一个项目使用了SpringBoot 1.5、Redis 5、Tomcat 8三种环境,其中Tomcat需要进行版本升级,Docker将其打包成镜像,现只需要升级该镜像并测试,后续的部署只需使用该镜像就可以了。服务器性能到瓶颈要水平扩展也更便捷- 更简单的系统运维
在容器化后,测试环境和线上环境高度一致- 更高效的计算资源利用
Docker是内核级别的虚拟化,可以在一个物理机上运行很多容器实例。服务器的性能可以发挥到极致
镜像(image):Docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,tomcat镜像 ==> run ==> tomcat01容器(提供服务)
容器(contianer):Docker利用容器技术独立运行一个或一组应用,容器是通过镜像来创建的。容器可以启动、停止、删除,都可以使用命令进行操作。目前可以把一个容器理解为是一个简易的Linux系统
仓库(repository):Docker仓库用来存放镜像,仓库分为公有仓库和私有仓库。DockerHub(默认是国外的)、阿里云等都有容器服务器(配置镜像加速)
环境准备:
[root@ziang ~]# uname -r # 查看系统内核版本 3.10.0-1127.19.1.el7.x86_64 [root@ziang ~]# cat /etc/os-release # 查看系统信息 NAME="CentOS Linux" VERSION="7 (Core)" ID="centos" ID_LIKE="rhel fedora" VERSION_ID="7" PRETTY_NAME="CentOS Linux 7 (Core)" ANSI_COLOR="0;31" CPE_NAME="cpe:/o:centos:centos:7" HOME_URL="https://www.centos.org/" BUG_REPORT_URL="https://bugs.centos.org/" CENTOS_MANTISBT_PROJECT="CentOS-7" CENTOS_MANTISBT_PROJECT_VERSION="7" REDHAT_SUPPORT_PRODUCT="centos" REDHAT_SUPPORT_PRODUCT_VERSION="7"
开始安装:
# 1. 卸载旧版本 yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine # 2. 需要的安装包 yum install -y yum-utils # 3. 设置镜像仓库 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 使用国内阿里云镜像仓库 # 更新yum软件包索引 yum makecache fast # 4. 安装Docker引擎:docker引擎、docker客户端、守护进程containerd yum install docker-ce docker-ce-cli containerd.io # 5. 启动Docker systemctl start docker # 6. 查看Docker版本信息 docker version # 7. Helloworld docker run hello-world # 8. 查看下载的hello-world镜像 docker images # 9. (另)卸载Docker yum remove docker-ce docker-ce-cli containerd.io rm -rf /var/lib/docker
Docker的默认工作路径(工作目录):/var/lib/docker
sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://f9ognzpb.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker
Docker是一个Client-Server架构的系统,Docker的守护进程运行在主机上,通过socket从客户端访问,docker-server接受到docker-client的指令就会执行
Docker为什么比VM快?
由图可见,新建容器时Docker无需像虚拟机那样重新加载一个操作系统内核。虚拟机加载Guest OS耗时在分钟级别,而Docker利用宿主机省略了这个过程,耗时是秒级
帮助命令
docker version docker版本信息 docker info docker配置信息,包括镜像和容器数量 docker 命令 --help docker帮助命令,万能
官方帮助文档地址:https://docs.docker.com/engine/reference/run/
查看本地所有镜像:docker images
[root@ziang /]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest feb5d9fea6a5 4 months ago 13.3kB rabbitmq management 246db2517862 8 months ago 186MB
# 列名解释 REPOSITORY 镜像的仓库源 TAG 镜像的标签 IMAGE ID 镜像的ID CREATE 镜像的创建时间 SIZE 镜像的大小 # 可选项 --all , -a Show all images (default hides intermediate images) --quiet , -q Only show image IDs
在镜像仓库中搜索镜像:docker search
[root@ziang ~]# docker search mysql NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 12047 [OK] mariadb MariaDB Server is a high performing open sou… 4618 [OK] mysql/mysql-server Optimized MySQL Server Docker images. Create… 901 [OK]
# 可选项:通过搜索过滤 --filter=STARS=3000 # 搜索出来STARS大于3000的命令
在镜像仓库中下载镜像:docker pull
[root@ziang ~]# docker pull mysql Using default tag: latest # 如果不指定tag,默认latest latest: Pulling from library/mysql 72a69066d2fe: Pull complete # 分层下载,docker image的核心,联合文件系统 93619dbc5b36: Pull complete 99da31dd6142: Pull complete 626033c43d70: Pull complete 37d5d7efb64e: Pull complete ac563158d721: Pull complete d2ba16033dad: Pull complete 688ba7d5c01a: Pull complete 00e060b6d11d: Pull complete 1c04857f594f: Pull complete 4d7cfa90e6ea: Pull complete e0431212d27d: Pull complete Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709 # 签名 Status: Downloaded newer image for mysql:latest docker.io/library/mysql:latest # 真实地址
# 以下两个命令等价 docker pull mysql docker pull docker.io/library/mysql:latest
# 指定版本下载 [root@ziang ~]# docker pull mysql:5.7 5.7: Pulling from library/mysql 72a69066d2fe: Already exists # 本地已存在的不再下载 93619dbc5b36: Already exists 99da31dd6142: Already exists 626033c43d70: Already exists 37d5d7efb64e: Already exists ac563158d721: Already exists d2ba16033dad: Already exists 0ceb82207cd7: Pull complete # 仅下载缺少的 37f2405cae96: Pull complete e2482e017e53: Pull complete 70deed891d42: Pull complete Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94 Status: Downloaded newer image for mysql:5.7 docker.io/library/mysql:5.7
删除镜像:docker rmi
# 指定tag删除 [root@ziang ~]# docker rmi -f c20987f18b13 Untagged: mysql:5.7 Untagged: mysql@sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94 Deleted: sha256:c20987f18b130f9d144c9828df630417e2a9523148930dc3963e9d0dab302a76 Deleted: sha256:6567396b065ee734fb2dbb80c8923324a778426dfd01969f091f1ab2d52c7989 Deleted: sha256:0910f12649d514b471f1583a16f672ab67e3d29d9833a15dc2df50dd5536e40f Deleted: sha256:6682af2fb40555c448b84711c7302d0f86fc716bbe9c7dc7dbd739ef9d757150 Deleted: sha256:5c062c3ac20f576d24454e74781511a5f96739f289edaadf2de934d06e910b92 # 删除多个镜像(后面跟多个tag即可) [root@ziang ~]# docker rmi -f c20987f18b13 feb5d9fea6a5 246db2517862 # 删除所有镜像 [root@ziang ~]# docker rmi -f $(docker images -aq)
说明:有了镜像才可以创建容器,所以需要先下载一个centos镜像:docker pull centos
新建容器并启动:docker run
docker run [可选参数] image # 可选参数 --name="dockerName" 容器名,用来区分容器 -d 以后台方式运行 -it 使用交互方式运行,进入容器查看内容 -p 指定容器端口,可以将主机端口映射到容器端口,方式有如下几种 -p ip:80:8080 主机ip:主机端口:容器端口 -p 80:8080 主机端口:容器端口(常用) -p 8080 容器端口 8080 容器端口 -P 随机指定端口
# 启动并进入容器 [root@ziang ~]# docker run -it centos /bin/bash # 使用交互式运行centos镜像,进入容器中查看内容。交互运行需要借助控制台,指定使用/bin/bash控制 [root@d034a3a4f9f3 /]# ls # 查看容器内,由于是基础版本,很多命令是不完善的 bin etc lib lost+found mnt proc run srv tmp var dev home lib64 media opt root sbin sys usr [root@d034a3a4f9f3 /]# exit # 退出容器 exit
查看容器:docker ps
[root@ziang ~]# docker ps # 查看当前正在运行的容器 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@ziang ~]# docker ps -a # 查看所有运行的容器(包括曾经运行过的容器) CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d034a3a4f9f3 centos "/bin/bash" 9 hours ago Exited (0) 9 hours ago vibrant_lamport 8b6f1b616774 centos "/bin/bash" 9 hours ago Exited (0) 7 hours ago strange_nash 548b160ded84 feb5d9fea6a5 "/hello" 10 hours ago Exited (0) 10 hours ago optimistic_proskuriakova 483aa315754d 246db2517862 "docker-entrypoint.s…" 8 months ago Created rabbitmq [root@ziang ~]# docker ps -a -n=1 # 查看最近运行的1个容器 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d034a3a4f9f3 centos "/bin/bash" 9 hours ago Exited (0) 9 hours ago vibrant_lamport [root@ziang ~]# docker ps -aq # 查看所有运行的容器,-q仅显示容器id d034a3a4f9f3 8b6f1b616774 548b160ded84 483aa315754d
退出容器:exit
exit # 停止容器并退出 Ctrl + P + Q # 不停止容器退出
删除容器:docker rm
docker rm 容器id # 删除指定容器id的容器,通过-f参数可删除正在运行的容器 docker rm -f $(docker ps -aq) # 删除所有容器 docker ps -a -a|xargs docker rm # 删除所有容器
启动和停止容器
docker start 容器id # 启动容器 docker restart 容器id # 重启容器 docker stop 容器id # 停止运行中的容器 docker kill 容器id # 强制停止容器
[root@ziang ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@ziang ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d034a3a4f9f3 centos "/bin/bash" 9 hours ago Exited (0) 9 hours ago vibrant_lamport [root@ziang ~]# docker start d034a3a4f9f3 d034a3a4f9f3 [root@ziang ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d034a3a4f9f3 centos "/bin/bash" 9 hours ago Up 3 seconds vibrant_lamport [root@ziang ~]# docker stop d034a3a4f9f3 d034a3a4f9f3 [root@ziang ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
docker容器的状态有:运行、停止。run启动容器进入运行状态,stop会让容器停止,rm会让容器消失(删除)
后台启动容器
docker run -d 容器image
以该方式启动容器后,使用docker ps命令并没有发现启动的容器,也就是说该容器停止了。docker容器使用后台运行,需要有一个前台进程,docker发现没有前台应用就会自动停止。比如启动一个Nginx,容器启动后发现自己没有提供服务,就会立刻停止
查看容器日志:docker logs
docker logs [可选参数] 容器id # 可选参数 -tf # 查看日志,t表示带有时间戳 --tail n # 显示最后n条日志
Demo:
[root@ziang ~]# docker run -d centos /bin/sh -c "while true;do echo ziang.zhang;sleep 1;done" 08a4ec2e85f9b73090ea5a11955bfaba9df3027f5174b00e52fc5592247697d9 [root@ziang ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 08a4ec2e85f9 centos "/bin/sh -c 'while t…" 4 seconds ago Up 3 seconds cool_hodgkin [root@ziang ~]# docker logs -tf --tail 10 08a4ec2e85f9 2022-02-03T01:19:31.160489316Z ziang.zhang 2022-02-03T01:19:32.162057672Z ziang.zhang 2022-02-03T01:19:33.163674626Z ziang.zhang 2022-02-03T01:19:34.165353081Z ziang.zhang 2022-02-03T01:19:35.167349305Z ziang.zhang 2022-02-03T01:19:36.169027025Z ziang.zhang 2022-02-03T01:19:37.170892402Z ziang.zhang 2022-02-03T01:19:38.172620267Z ziang.zhang 2022-02-03T01:19:39.174546190Z ziang.zhang 2022-02-03T01:19:40.176468912Z ziang.zhang 2022-02-03T01:19:41.178292254Z ziang.zhang
查看容器中的进程信息:docker top
docker top 容器id
[root@ziang ~]# docker top 08a4ec2e85f9 UID PID PPID C STIME TTY TIME CMD root 4578 4558 0 09:18 ? 00:00:00 /bin/sh -c while true;do echo ziang.zhang;sleep 1;done root 5181 4578 0 09:27 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
查看容器元数据:docker inspect
docker inspect 容器id
[root@ziang ~]# docker inspect 08a4ec2e85f9 [ { "Id": "08a4ec2e85f9b73090ea5a11955bfaba9df3027f5174b00e52fc5592247697d9", "Created": "2022-02-03T01:18:56.873267955Z", "Path": "/bin/sh", "Args": [ "-c", "while true;do echo ziang.zhang;sleep 1;done" ], "State": { "Status": "running", "Running": true, "Paused": false, "Restarting": false, "OOMKilled": false, "Dead": false, "Pid": 4578, "ExitCode": 0, "Error": "", "StartedAt": "2022-02-03T01:18:57.079480925Z", "FinishedAt": "0001-01-01T00:00:00Z" }, "Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6", "ResolvConfPath": "/var/lib/docker/containers/08a4ec2e85f9b73090ea5a11955bfaba9df3027f5174b00e52fc5592247697d9/resolv.conf", "HostnamePath": "/var/lib/docker/containers/08a4ec2e85f9b73090ea5a11955bfaba9df3027f5174b00e52fc5592247697d9/hostname", "HostsPath": "/var/lib/docker/containers/08a4ec2e85f9b73090ea5a11955bfaba9df3027f5174b00e52fc5592247697d9/hosts", "LogPath": "/var/lib/docker/containers/08a4ec2e85f9b73090ea5a11955bfaba9df3027f5174b00e52fc5592247697d9/08a4ec2e85f9b73090ea5a11955bfaba9df3027f5174b00e52fc5592247697d9-json.log", "Name": "/cool_hodgkin", "RestartCount": 0, "Driver": "overlay2", "Platform": "linux", "MountLabel": "", "ProcessLabel": "", "AppArmorProfile": "", "ExecIDs": null, "HostConfig": { "Binds": null, "ContainerIDFile": "", "LogConfig": { "Type": "json-file", "Config": {} }, "NetworkMode": "default", "PortBindings": {}, "RestartPolicy": { "Name": "no", "MaximumRetryCount": 0 }, "AutoRemove": false, "VolumeDriver": "", "VolumesFrom": null, "CapAdd": null, "CapDrop": null, "CgroupnsMode": "host", "Dns": [], "DnsOptions": [], "DnsSearch": [], "ExtraHosts": null, "GroupAdd": null, "IpcMode": "private", "Cgroup": "", "Links": null, "OomScoreAdj": 0, "PidMode": "", "Privileged": false, "PublishAllPorts": false, "ReadonlyRootfs": false, "SecurityOpt": null, "UTSMode": "", "UsernsMode": "", "ShmSize": 67108864, "Runtime": "runc", "ConsoleSize": [ 0, 0 ], "Isolation": "", "CpuShares": 0, "Memory": 0, "NanoCpus": 0, "CgroupParent": "", "BlkioWeight": 0, "BlkioWeightDevice": [], "BlkioDeviceReadBps": null, "BlkioDeviceWriteBps": null, "BlkioDeviceReadIOps": null, "BlkioDeviceWriteIOps": null, "CpuPeriod": 0, "CpuQuota": 0, "CpuRealtimePeriod": 0, "CpuRealtimeRuntime": 0, "CpusetCpus": "", "CpusetMems": "", "Devices": [], "DeviceCgroupRules": null, "DeviceRequests": null, "KernelMemory": 0, "KernelMemoryTCP": 0, "MemoryReservation": 0, "MemorySwap": 0, "MemorySwappiness": null, "OomKillDisable": false, "PidsLimit": null, "Ulimits": null, "CpuCount": 0, "CpuPercent": 0, "IOMaximumIOps": 0, "IOMaximumBandwidth": 0, "MaskedPaths": [ "/proc/asound", "/proc/acpi", "/proc/kcore", "/proc/keys", "/proc/latency_stats", "/proc/timer_list", "/proc/timer_stats", "/proc/sched_debug", "/proc/scsi", "/sys/firmware" ], "ReadonlyPaths": [ "/proc/bus", "/proc/fs", "/proc/irq", "/proc/sys", "/proc/sysrq-trigger" ] }, "GraphDriver": { "Data": { "LowerDir": "/var/lib/docker/overlay2/666f081c125b11f2c166ce349a8e6bce578d4720b1b76fdc6afd58b7c6993f43-init/diff:/var/lib/docker/overlay2/ab82fd3f5f7dfd160f732a74032059d85648202a69601a95239ef244ea6a4c3f/diff", "MergedDir": "/var/lib/docker/overlay2/666f081c125b11f2c166ce349a8e6bce578d4720b1b76fdc6afd58b7c6993f43/merged", "UpperDir": "/var/lib/docker/overlay2/666f081c125b11f2c166ce349a8e6bce578d4720b1b76fdc6afd58b7c6993f43/diff", "WorkDir": "/var/lib/docker/overlay2/666f081c125b11f2c166ce349a8e6bce578d4720b1b76fdc6afd58b7c6993f43/work" }, "Name": "overlay2" }, "Mounts": [], "Config": { "Hostname": "08a4ec2e85f9", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/sh", "-c", "while true;do echo ziang.zhang;sleep 1;done" ], "Image": "centos", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": { "org.label-schema.build-date": "20210915", "org.label-schema.license": "GPLv2", "org.label-schema.name": "CentOS Base Image", "org.label-schema.schema-version": "1.0", "org.label-schema.vendor": "CentOS" } }, "NetworkSettings": { "Bridge": "", "SandboxID": "b3eb26048d3703c07248154ca751b1c05e9cdcdced88e3df18da451914c555fd", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": {}, "SandboxKey": "/var/run/docker/netns/b3eb26048d37", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "54ca19d0722608eb645ee47d5e07d482b2d5cfe6533591d3cc33e6912e5a14a4", "Gateway": "172.17.0.1", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "MacAddress": "02:42:ac:11:00:02", "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "7b73a049c8d1d281d8c66fe3dc1471696c813349d7e543123860c0f82c5aba97", "EndpointID": "54ca19d0722608eb645ee47d5e07d482b2d5cfe6533591d3cc33e6912e5a14a4", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:02", "DriverOpts": null } } } } ]
进入正在运行的容器
我们通常使用后台方式运行容器,进入容器可以选择以下两种方式:
方式1:docker exec -it 容器id /bin/bash
(常用)
方式2:docker attach 容器id
前者进入容器会开启一个新的终端,后者进入容器正在执行的终端,不会开启新的终端
从容器内拷贝文件到主机
docker cp 容器id:容器路径 主机路径
attach Attach to a running container # 当前shell下attach连接指定运行镜像 build Build an image from a Dockerfile # 通过Dockerfile定制镜像 commit Create a new image from a container changes # 提交当前容器为新的镜像 cp Copy files/folders from the containers filesystem to the host path # 从容器中拷贝指定文件或者目录到宿主机中 create Create a new container # 创建一个新容器,同run,但不启动容器 diff Inspect changes on a container # 查看docker容器变化 events Get real time events from the server # 从docker服务获取容器实时事件 exec Run a command in an existing container # 在已存在的容器上运行命令 export Stream the contents of a container as a tar archive # 导出容器的内容流作为一个tar归档文件[对应 import] history Show the history of an image # 展示一个镜像形成历史 images List images # 列出系统当前镜像 import Create a new filesystem image from the contents of a tarball # 从tar包中的内容创建一个新的文件系统镜像[对应 export] info Display system-wide information # 显示系统相关信息 inspect Return low-level information on a container # 查看容器详细信息 kill Kill a runing container # kill指定docker容器 load Load an image from a tar archive # 从一个tar包中加载一个镜像[对应 save] login Register or Login to the docker registry server # 注册或登陆一个docker源服务器 logout Log out from a Docker registry server # 从当前Docker registry退出 logs Fetch the logs of a container # 输出当前容器日志信息 port Lookup the public-facing port which is NAT-ed to PRIVATE_PORT # 查看映射端口对应的容器内部源端口 pause Pause all processes within a container # 暂停容器 ps List containers # 列出容器列表 pull Pull an image or a repository from the docker registry server # 从docker镜像源服务器拉取指定镜像或库镜像 push Push an image or repository to the docker registry server # 推送指定镜像或库镜像至docker源服务器 restart Restart a running container. # 重启运行的容器 rm Remove one or more container. # 移除一个或多个容器 rmi Remove one or more images # 移除一个或多个镜像[无容器使用该镜像才可删除,否则需要先删除该容器或-f强制删除] run Run a command in a new container. # 创建一个新的容器并运行一个命令 save Save an image to a tar archive. # 保存一个镜像为一个tar包[对应 load] search Search for an image on the Docker Hub # 在docker hub中搜索镜像 start Start a stopped containers # 启动容器 stop Stop a running containers # 停止容器 tag Tag # 查看容器中运行的进程信息 unpause Unpause a paused container # 取消暂停容器 version Show the docker version informatioins # 查看docker版本号 wait Block until a container stops, then print its exit code # 截取容器停止时的推出状态值
[root@ziang ~]# docker pull nginx Using default tag: latest latest: Pulling from library/nginx a2abf6c4d29d: Pull complete a9edb18cadd1: Pull complete 589b7251471a: Pull complete 186b1aaa4aa6: Pull complete b4df32aa5a72: Pull complete a0bcbecc962e: Pull complete Digest: sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31 Status: Downloaded newer image for nginx:latest docker.io/library/nginx:latest [root@ziang ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 605c77e624dd 5 weeks ago 141MB centos latest 5d0da3dc9764 4 months ago 231MB # -d 后台运行 # --name 给容器命名 # -p 宿主机端口:容器内部端口 [root@ziang ~]# docker run -d --name nginx01 -p:3344:80 nginx f7ff85d30a3099f60b88de8ec4db877ceed5a1b27722ccc5bee4b333cd7c3eb5 [root@ziang ~]# curl localhost:3344 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
端口暴露概念
什么是portainer?
一个Docker图形化界面管理工具,提供可操作的后台面板。使用以下命令启动potainer:
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/potainer
通过浏览器http://ip:8088/访问,可以看到如下登陆界面:
进入之后就可以根据可视化面板控制
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。简单来说就是应用直接打包为docker镜像就可以运行起来。
如何得到镜像:
UnionFS(联合文件系统)
UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite serveral directories into a single virtual filesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
Docker镜像加载原理
Docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
dootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux\Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
rootfs(root file system),在bootfs之上,包含的就是典型Linux系统中的/dev、/proc、/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu、CentOS等等。
平时我们安装进虚拟机的CentOS大概几个G大小,但为什么Docker的镜像只有200M?
对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的Linux发行版,rootfs基本是一致的,rootfs会有差别,因此不同的发行版可以共用bootfs。
下载镜像观察打印的日志输出,可以看出镜像是一层一层下载的
[root@ziang ~]# docker pull redis Using default tag: latest latest: Pulling from library/redis a2abf6c4d29d: Already exists c7a4e4382001: Pull complete 4044b9ba67c9: Pull complete c8388a79482f: Pull complete 413c8bb60be2: Pull complete 1abfd3011519: Pull complete Digest: sha256:db485f2e245b5b3329fdc7eff4eb00f913e09d8feb9ca720788059fdc2ed8339 Status: Downloaded newer image for redis:latest docker.io/library/redis:latest
理解:
所有的Docker镜像都起始于一个基础镜像,当进行修改或增加新的内容时,就会中当前镜像层上创建新的镜像层。
比如基于Ubuntu Linux 16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加Python包,就会在基础镜像层上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
该镜像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。
在添加额外镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件。
上图的镜像层跟之前图中的略有区别,主要目的是便于展示文件。
下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版本。
这种情况下,上层镜像层中文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。
Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
Linux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker在Windows上仅支持windowsfilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和Cow。
下图展示了与系统展示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。
Docker镜像层都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。这一层就是我们通常说的容器层,容器之下的都叫镜像层。我们的所有操作都是基于容器层的
docker commit # 提交容器成为一个新的副本 docker commit -m="commit note" -a="author" 容器id 目标镜像名:[TAG] # 命令和git类似
Demo:
# 1.启动一个tomcat容器 [root@ziang ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7d7f032ea599 tomcat "catalina.sh run" 9 minutes ago Up 2 minutes 0.0.0.0:8080->8080/tcp nervous_maxwell f7ff85d30a30 nginx "/docker-entrypoint.…" 7 days ago Up 7 days 0.0.0.0:3344->80/tcp nginx01 08a4ec2e85f9 centos "/bin/sh -c 'while t…" 7 days ago Up 7 days cool_hodgkin [root@ziang ~]# docker exec -it 7d7f0 /bin/bash root@7d7f032ea599:/usr/local/tomcat# ls webappps # 2.tomcat官方镜像默认webapps目录下是空的,拷贝基本文件到webapps目录下 root@7d7f032ea599:/usr/local/tomcat# ls BUILDING.txt CONTRIBUTING.md LICENSE NOTICE README.md RELEASE-NOTES RUNNING.txt bin conf lib logs native-jni-lib temp webapps webapps.dist work root@7d7f032ea599:/usr/local/tomcat# cp -r webapps.dist/* webapps root@7d7f032ea599:/usr/local/tomcat# ls webapps ROOT docs examples host-manager manager # 3.将操作过的容器commit为一个镜像。以后可以使用该镜像启动容器 [root@ziang ~]# docker commit -a="ziang.zhang" -m="add some files to webapps" 7d7f03 tomcat.ziang.1.0 sha256:3418d38b10501944949f7230ad332d930e149a20294ee7f4e92d05b4ebd262e9 # 4.查看刚刚提交的镜像tomcat.ziang.1.0,发现它比tomcat大13MB,这就是cp操作后的结果 [root@ziang ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE tomcat.ziang.1.0 latest 3418d38b1050 9 seconds ago 693MB nginx latest 605c77e624dd 6 weeks ago 141MB tomcat latest fb5657adc892 7 weeks ago 680MB redis latest 7614ae9453d1 7 weeks ago 113MB centos latest 5d0da3dc9764 4 months ago 231MB portainer/portainer latest 580c0e4e98b0 10 months ago 79.1MB
如果想保存容器的状态,就可以通过commit来提交,获得一个新镜像
学完以上命令,Docker学习才正式入门
Docker将应用与环境打包成镜像,通过镜像启动容器。思考两个问题:
所以Docker应该有一个持久化和同步数据的机制,将容器中产生的数据同步到本地,这个机制就是容器数据卷,将容器内的目录挂在到本地目录
使用容器数据卷技术,可以将主机目录与容器内目录进行挂载,在其中一个目录更新了内容,另一个目录就会进行同步更新。另外,只要该容器存在,无论启动与否,数据的同步仍在进行。如果该容器被rm,那么数据将依然存在,但同步将不再
总结:容器数据卷是容器数据的持久化和同步技术,各个容器之间也可以使用该技术。
方式一:启动容器时使用-v参数
docker run -it -v 主机目录1:容器目录1 -v 主机目录2:容器目录2 ...
实战:安装MySQL并使用容器数据卷
1.docker pull mysql:5.7 # 参数 -d 后台启动 -p 端口暴露 -v 数据卷挂载 -e 环境变量配置 --name 容器命名 2.docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7 3.启动成功后,使用MySQL图形界面连接到服务器的3306端口,创建一个数据库并在其中创建表进行插入操作 4.去服务器/home/mysql/data目录下查看是否创建了该目录(数据库)与文件(表)
宿主机的挂载目录与容器中的挂载目录不存在时都会自动创建
# 匿名挂载:-v 容器目录(仅指定容器目录) [root@ziang ~]# docker run -d -P -v /etc/nginx --name nginx02 nginx # -P 随机指定端口 61dacb811c228b36fea583509bd303dcc2c22647631e6cfe2ca780c353bb29ef # 查看所有容器数据卷情况,每一条数据代表一个真实存在的目录 [root@ziang ~]# docker volume ls DRIVER VOLUME NAME local 26cd6fb4a595803c408f4b43f2fb97ca46df35a2ca6634ee3dded63a5b7ed235 local 922e29647b7fcc546841088a0e9580e79c849cd669096ce306cd2c74b4d464a0 local 62326bf1e0e8601ca8e2f0961d54deae6de13d05a605b1a242551592a1a36236 local d7331eebf78e6fe7e5793efc256a3dacec290d698c28fd6eabc98a0a06b6176d local e5300d1e74f17909816fc94b1445e7e686d27283fff2047d7128026392dad324 # 具名挂载:-v 卷名/容器目录 [root@ziang ~]# docker run -d -P -v juming-nginx:/etc/nginx --name nginx03 nginx 59d2cc2ba71fb03c01a7beb42ced116345498ecf25a60c43a411ec395aeb3dd8 [root@ziang ~]# docker volume ls DRIVER VOLUME NAME local 26cd6fb4a595803c408f4b43f2fb97ca46df35a2ca6634ee3dded63a5b7ed235 local 922e29647b7fcc546841088a0e9580e79c849cd669096ce306cd2c74b4d464a0 local 62326bf1e0e8601ca8e2f0961d54deae6de13d05a605b1a242551592a1a36236 local d7331eebf78e6fe7e5793efc256a3dacec290d698c28fd6eabc98a0a06b6176d local e5300d1e74f17909816fc94b1445e7e686d27283fff2047d7128026392dad324 local juming-nginx # 查看目录位置(在没有指定目录的情况下,所有挂载的目录都在/var/lib/docker/volumes/下) [root@ziang ~]# docker volume inspect juming-nginx [ { "CreatedAt": "2022-02-15T23:20:50+08:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data", "Name": "juming-nginx", "Options": null, "Scope": "local" } ]
通过具名挂载可以方便地找到该卷,多数情况下使用具名挂载
如何确认使用何种方式挂载?
拓展:
# -v 容器内路径:ro ro readonly 只读,数据只能在外部改变,容器内部只能读数据 docker run -d -P -v juming-nginx:/etc/nginx:ro --name nginx03 nginx # -v 容器内路径:rw rw readrwrite 可写,数据可以在外部改变,也可以在内部改变 docker run -d -P -v juming-nginx:/etc/nginx:rw --name nginx03 nginx # 一旦设置了该权限,挂载出来的内容就会存在限定。 # 只要看到ro,就说明该目录内容只能由宿主机来操作,容器内部无法操作
DockerFile是用来构建docker镜像的文件,内容是命令脚本,可以通过它生成镜像。
镜像是一层一层的结构,而DockerFile的每一行命令就对应其中一层
[root@ziang containerDataVolume]# vim dockerfile1 [root@ziang containerDataVolume]# cat dockerfile1 FROM centos # 使用基础镜像 VOLUME ["volume01","volume02"] # 挂载数据卷(匿名挂载) CMD echo "----- end -----" # 执行 CMD /bin/bash # -f dockerfile路径;-t 镜像名 [root@ziang containerDataVolume]# docker build -f dockerfile1 -t ziangTest/centos . Sending build context to Docker daemon 4.608kB Step 1/4 : FROM centos ---> 5d0da3dc9764 Step 2/4 : VOLUME ["volume01","volume02"] ---> Running in 914d32002e92 Removing intermediate container 914d32002e92 ---> a45fc8e2da0a Step 3/4 : CMD echo "----- end -----" ---> Running in d574aa3ce16b Removing intermediate container d574aa3ce16b ---> cff2dd066931 Step 4/4 : CMD /bin/bash ---> Running in e44806b5d641 Removing intermediate container e44806b5d641 ---> e3771927547f Successfully built e3771927547f Successfully tagged ziangTest/centos:latest [root@ziang containerDataVolume]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE ziangTest/centos latest e3771927547f 4 minutes ago 231MB tomcat.ziang.1.0 latest 3418d38b1050 5 days ago 693MB nginx latest 605c77e624dd 6 weeks ago 141MB tomcat latest fb5657adc892 7 weeks ago 680MB redis latest 7614ae9453d1 8 weeks ago 113MB mysql latest 3218b38490ce 8 weeks ago 516MB centos latest 5d0da3dc9764 5 months ago 231MB portainer/portainer latest 580c0e4e98b0 11 months ago 79.1MB [root@ziang ~]# docker run -it ziangTest/centos /bin/bash [root@547072811dc7 /]# ls -l total 56 lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin drwxr-xr-x 5 root root 360 Feb 16 13:28 dev drwxr-xr-x 1 root root 4096 Feb 16 13:28 etc drwxr-xr-x 2 root root 4096 Nov 3 2020 home lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64 drwx------ 2 root root 4096 Sep 15 14:17 lost+found drwxr-xr-x 2 root root 4096 Nov 3 2020 media drwxr-xr-x 2 root root 4096 Nov 3 2020 mnt drwxr-xr-x 2 root root 4096 Nov 3 2020 opt dr-xr-xr-x 110 root root 0 Feb 16 13:28 proc dr-xr-x--- 2 root root 4096 Sep 15 14:17 root drwxr-xr-x 11 root root 4096 Sep 15 14:17 run lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin drwxr-xr-x 2 root root 4096 Nov 3 2020 srv dr-xr-xr-x 13 root root 0 Feb 16 13:28 sys drwxrwxrwt 7 root root 4096 Sep 15 14:17 tmp drwxr-xr-x 12 root root 4096 Sep 15 14:17 usr drwxr-xr-x 20 root root 4096 Sep 15 14:17 var drwxr-xr-x 2 root root 4096 Feb 16 13:28 volume01 # 挂载目录1 drwxr-xr-x 2 root root 4096 Feb 16 13:28 volume02 # 挂载目录2 [root@73216b2be2dd volume01]# exit exit [root@ziang ~]# docker inspect 73216b2be2dd # 在Mounts中可看到该容器的数据卷挂载信息
这种方式比较常见,可以在构建自己的镜像时进行卷挂载;若没有中构建镜像时挂载,则可以在启动容器的时候使用-v参数进行挂载
Demo:
[root@ziang ~]# docker run -it --name dockerA ziang/centos [root@ziang ~]# docker run -it --name dockerB --volumes-from dockerA ziang/centos [root@ziang ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f406eff2f33c ziang/centos "/bin/sh -c /bin/bash" 39 seconds ago Up 38 seconds dockerB 671c33eb072f ziang/centos "/bin/sh -c /bin/bash" About a minute ago Up About a minute dockerA [root@ziang ~]# docker attach 671c33eb072f [root@671c33eb072f /]# ls bin etc lib lost+found mnt proc run srv tmp var volume02 dev home lib64 media opt root sbin sys usr volume01 [root@671c33eb072f /]# cd volume01 [root@671c33eb072f volume01]# touch abc.java [root@671c33eb072f volume01]# read escape sequence # ctrl + p + q [root@ziang ~]# docker attach f406eff2f33c [root@f406eff2f33c /]# cd volume01 [root@f406eff2f33c volume01]# ls abc.java # dockerA创建的文件同步到了dockerB,相当于A被B继承,A就是数据卷容器 [root@ziang ~]# docker run -it --name dockerC --volumes-from dockerA ziang/centos [root@aaf87d82d739 /]# ls bin etc lib lost+found mnt proc run srv tmp var volume02 dev home lib64 media opt root sbin sys usr volume01 [root@aaf87d82d739 /]# cd volume01 [root@aaf87d82d739 volume01]# ls abc.java # 再创建一个dockerC同步挂载dockerA,该文件也存在 [root@ziang ~]# docker rm -f 671c33eb072f 671c33eb072f [root@ziang ~]# docker attch f406eff2f33c docker: 'attch' is not a docker command. See 'docker --help' [root@ziang ~]# docker attach f406eff2f33c [root@f406eff2f33c volume01]# ls abc.java # 删除dockerA,其他容器仍存在该文件
对多个MySQL容器进行数据同步
[root@ziang ~]# docker run -d -p 3345:3306 --name mysqlA -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7 [root@ziang ~]# docker run -d -p 3346:3306 --name mysqlB -e MYSQL_ROOT_PASSWORD=123456 --volumes-from mysqlA mysql:5.7
总结:可以实现容器间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止
Dockerfile是用来构建Docker镜像的文件,一个命令参数脚本
构建步骤:
很多官方镜像都是基础包,很多功能没有,需要用户按需求搭建自己的镜像
基础知识:
DockerFile是面向开发的,以后要发布项目做镜像,就需要编写DockerFile文件,这个文件十分简单
Docker镜像逐渐成为企业交付的标准
FROM # 基础镜像,一切从这里开始构建 MAINTAINER # 镜像是由谁编写的,姓名+邮箱 RUN # 镜像构建时需要运行的命令 ADD # 构建步骤,比如搭建一个tomcat镜像,需要加入一个tomcat的压缩包,即添加内容 WORKDIR # 镜像的工作目录 VOLUME # 设置容器卷,挂载的目录 EXPOSE # 暴露端口,写了该参数就不需要在run -p中指定端口 CMD # 指定该容器启动时(docker run)要运行的命令,只有最后一个会生效,可被替代 ENTRYPOINT # 指定该容器启动时(docker run)要运行的命令,可以追加命令 ONBUILD # 当构建一个被继承的DockerFile,这个时候会运行 ONBUILD的指令(触发指令) COPY # 类似ADD,将文件拷贝到镜像中 ENV # 构建时设置环境变量
DockerHub中99%的镜像都是从基础镜像scratch开始的,然后添加需要的配置和软件进行构建
Demo:
# 1.编写Dockerfile文件 [root@ziang dockerfile]# cat dockerfile-mycentoscat dockerfile-mycentos FROM centos # 从centos开始构建 MAINTAINER ziangzhang<tzuaness@gmail.com> # 构建人信息 ENV MYPATH /use/local # 设置环境变量 WORKDIR $MYPATH # 工作目录(一进入镜像就会首先在工作目录) RUN yum -y install vim # 下载vim RUN yum -y install net-tools # 下载net-tools EXPOSE 80 # 暴露端口 CMD echo $MYPATH CMD echo "---end---" CMD /bin/bash # 2.通过文件构建镜像 # docker build -f dockerfile文件路径 -t 镜像名:版本号 [root@ziang dockerfile]# cat dockerfile-mycentosdocker build -f dockerfile-mycentos -t mycentos:0.1 .
列出镜像的变更历史:docker history 镜像id/镜像名
CMD # 指定该容器启动时(docker run)要运行的命令,只有最后一个会生效,可被替代 ENTRYPOINT # 指定该容器启动时(docker run)要运行的命令,可以追加命令
Demo:
# CMD [root@ziang dockerfile]# cat dockerfile-cmd-test FROM tomcat CMD ["ls","-a"] [root@ziang dockerfile]# docker build -f dockerfile-cmd-test -t dockerfile-cmd:0.1 . Sending build context to Docker daemon 4.096kB Step 1/2 : FROM tomcat ---> fb5657adc892 Step 2/2 : CMD ["ls","-a"] ---> Using cache ---> 9e26f3ba0a87 Successfully built 9e26f3ba0a87 Successfully tagged dockerfile-cmd:0.1 [root@ziang dockerfile]# docker run dockerfile-cmd:0.1 . .. BUILDING.txt CONTRIBUTING.md LICENSE NOTICE README.md RELEASE-NOTES RUNNING.txt bin conf lib logs native-jni-lib temp webapps webapps.dist work # 想在运行该容器时追加一个命令-l想达到ls -al的效果,但在CMD下-l替换了CMD ["ls","-a"],-l并非命令,所以报错 [root@ziang dockerfile]# docker run dockerfile-cmd:0.1 -l docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "-l": executable file not found in $PATH: unknown. ERRO[0000] error waiting for container: context canceled # ENTRYPOINT [root@ziang dockerfile]# cat dockerfile-entrypoint-test FROM tomcat ENTRYPOINT ["ls","-a"] [root@ziang dockerfile]# docker build -f dockerfile-entrypoint-test -t dockerfile-entrypoint:0.1 . Sending build context to Docker daemon 4.096kB Step 1/2 : FROM tomcat ---> fb5657adc892 Step 2/2 : ENTRYPOINT ["ls","-a"] ---> Running in 43fa27dc91b0 Removing intermediate container 43fa27dc91b0 ---> e95e71dd650b Successfully built e95e71dd650b Successfully tagged dockerfile-entrypoint:0.1 [root@ziang dockerfile]# docker run dockerfile-entrypoint:0.1 . .. BUILDING.txt CONTRIBUTING.md LICENSE NOTICE README.md RELEASE-NOTES RUNNING.txt bin conf lib logs native-jni-lib temp webapps webapps.dist work [root@ziang dockerfile]# docker run dockerfile-entrypoint:0.1 -l total 168 drwxr-xr-x 1 root root 4096 Dec 22 17:07 . drwxr-xr-x 1 root root 4096 Dec 22 17:00 .. -rw-r--r-- 1 root root 18994 Dec 2 22:01 BUILDING.txt -rw-r--r-- 1 root root 6210 Dec 2 22:01 CONTRIBUTING.md -rw-r--r-- 1 root root 60269 Dec 2 22:01 LICENSE -rw-r--r-- 1 root root 2333 Dec 2 22:01 NOTICE -rw-r--r-- 1 root root 3378 Dec 2 22:01 README.md -rw-r--r-- 1 root root 6905 Dec 2 22:01 RELEASE-NOTES -rw-r--r-- 1 root root 16517 Dec 2 22:01 RUNNING.txt drwxr-xr-x 2 root root 4096 Dec 22 17:07 bin drwxr-xr-x 2 root root 4096 Dec 2 22:01 conf drwxr-xr-x 2 root root 4096 Dec 22 17:06 lib drwxrwxrwx 2 root root 4096 Dec 2 22:01 logs drwxr-xr-x 2 root root 4096 Dec 22 17:07 native-jni-lib drwxrwxrwx 2 root root 4096 Dec 22 17:06 temp drwxr-xr-x 2 root root 4096 Dec 22 17:06 webapps drwxr-xr-x 7 root root 4096 Dec 2 22:01 webapps.dist drwxrwxrwx 2 root root 4096 Dec 2 22:01 work
1 准备镜像文件:Tomcat压缩包,JDK压缩包
2 编写Dockerfile,官方命名即Dockerfile
,docker build会自动寻找该命名的文件,无需再通过-f参数指定
FROM centos MAINTAINER ziang.zhang<tzuaness@gmail.com> COPY readme.txt /usr/local/readme.txt ADD apache-tomcat-9.0.33.tar.gz /usr/local/ ADD jdk-8u65-linux-x64.rpm /usr/local/ RUN yum -y install vim ENV MYWORKPATH /usr/local ENV JAVA_HOME /usr/local/jdk1.8.0_65 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/toos.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.33 ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.33 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin WORKDIR $MYWORKPATH EXPOSE 8080 CMD /usr/local/apache-tomcat-9.0.33/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.33/bin/logs/catalina.out
[root@ziang zhangziang]# ls apache-tomcat-9.0.33.tar.gz readme.txt Dockerfile redis-6.0.6.tar.gz jdk-8u65-linux-x64.rpm [root@ziang zhangziang]# vim Dockerfile [root@ziang zhangziang]# cat Dockerfile FROM centos MAINTAINER ziang.zhang<tzuaness@gmail.com> COPY readme.txt /usr/local/readme.txt COPY jdk-8u65-linux-x64.rpm /usr/local/ ADD apache-tomcat-9.0.33.tar.gz /usr/local/ RUN yum -y install vim RUN rpm -ivh /usr/local/jdk-8u65-linux-x64.rpm ENV MYWORKPATH /usr/local ENV JAVA_HOME /usr/java/jdk1.8.0_65 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/toos.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.33 ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.33 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin WORKDIR $MYWORKPATH EXPOSE 8080 CMD /usr/local/apache-tomcat-9.0.33/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.33/bin/logs/catalina.out [root@ziang zhangziang]# docker build -t zomcat:0.1 . [root@ziang zhangziang]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE zomcat 0.1 49635e747d1d 2 minutes ago 407MB # 挂载数据卷时,宿主机与容器中没有的目录会自动创建。挂载webapps目录后,发布的项目可以直接放置在本地 [root@ziang zhangziang]# docker run -d -p 9090:8080 --name ziangtomcat -v /home/zhangziang/tomcat/webapps:/usr/local/apache-tomcat-9.0.33/webapps/test -v /home/zhangziang/tomcat/logs:/usr/local/apache-tomcat-9.0.33/logs zomcat:0.1
发布到DockerHub
docker login
命令进行登陆docker push
命令将自己的镜像发布到DockerHub中发布到阿里云镜像仓库
相关命令: $ docker login --username=tz**** registry.cn-hangzhou.aliyuncs.com $ docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/ziang_repository/demo01:[镜像版本号] $ docker push registry.cn-hangzhou.aliyuncs.com/ziang_repository/demo01:[镜像版本号] $ docker pull registry.cn-hangzhou.aliyuncs.com/ziang_repository/demo01:[镜像版本号]
三个网络分别代表三种环境,那么Docker是如何处理容器网络访问的?