狂神說docker(最全筆記)
(7條消息) 狂神說Docker進階筆記_興趣使然的草帽路飛-CSDN博客_狂神說docker進階筆記
筆記來源於
Docker https://www.bilibili.com/video/BV1og4y1q7M4 視頻整理
一.Docker入門
1. Docker 爲什麼會出現
2. Docker的歷史
3. Docker最新超詳細版教程通俗易懂
Docker是基於Go語言開發的!開源項目
官網
官方文檔Docker文檔是超詳細的
倉庫地址
4. 虛擬化技術和容器化技術對比
4.1. 虛擬化技術的缺點
資源佔用十分多
冗餘步驟多
啓動很慢
2.2. 容器化技術
4.3. DevOps
sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://pi9dpp60.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker
4.2 安裝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
$ 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 安裝完默認未啓動。並且已經創建好 docker 用戶組,但該用戶組下沒有用戶。
要安裝特定版本的 Docker Engine-Community,請在存儲庫中列出可用版本,然後選擇並安裝:
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
2、通過其完整的軟件包名稱安裝特定版本,該軟件包名稱是軟件包名稱(docker-ce)加上版本字符串(第二列),從第一個冒號(:)一直到第一個連字符,並用連字符(-)分隔。例如:docker-ce-18.09.1。
$ sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
啓動 Docker。
$ sudo systemctl start docker
通過運行 hello-world 映像來驗證是否正確安裝了 Docker Engine-Community 。
$ sudo docker run hello-world
5. 底層原理
HelloWorld鏡像
二,Docker基本命令
1. Docker的常用命令
幫助命令
docker version # docker版本信息
docker info # 系統級別的信息,包括鏡像和容器的數量
docker 命令 --help
鏡像命令
docker images 查看所有本地主機上的鏡像
[root@iZ2zeg4ytp0whqtmxbsqiiZ ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest bf756fb1ae65 7 months ago 13.3kB # 解釋 REPOSITORY # 鏡像的倉庫 TAG # 鏡像的標籤 IMAGE ID # 鏡像的ID CREATED # 鏡像的創建時間 SIZE # 鏡像的大小 # 可選項 --all , -a # 列出所有鏡像 --quiet , -q # 只顯示鏡像的id
docker search 查找鏡像
NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 9822 [OK] mariadb MariaDB is a community-developed fork of MyS… 3586 [OK] mysql/mysql-server Optimized MySQL Server Docker images. Create… 719 [OK] # 可選項 --filter=STARS=3000 # 搜素出來的鏡像就是STARS大於3000的 [root@iZ2zeg4ytp0whqtmxbsqiiZ ~]# docker search mysql --filter=STARS=3000 NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 9822 [OK] mariadb MariaDB is a community-developed fork of MyS… 3586 [OK]
docker pull 下拉鏡像
# 下載鏡像,docker pull 鏡像名[:tag] [root@iZ2zeg4ytp0whqtmxbsqiiZ ~]# docker pull mysql Using default tag: latest # 如果不寫tag,默認就是latest latest: Pulling from library/mysql bf5952930446: Pull complete # 分層下載,dockerimages的核心,聯合文件系統 8254623a9871: Pull complete 938e3e06dac4: Pull complete ea28ebf28884: Pull complete f3cef38785c2: Pull complete 894f9792565a: Pull complete 1d8a57523420: Pull complete 6c676912929f: Pull complete ff39fdb566b4: Pull complete fff872988aba: Pull complete 4d34e365ae68: Pull complete 7886ee20621e: Pull complete Digest: sha256:c358e72e100ab493a0304bda35e6f239db2ec8c9bb836d8a427ac34307d074ed # 簽名 Status: Downloaded newer image for mysql:latest docker.io/library/mysql:latest # 真實地址 # 等價於 docker pull mysql docker pull docker.io/library/mysql:latest # 指定版本下載 [root@iZ2zeg4ytp0whqtmxbsqiiZ ~]# docker pull mysql:5.7 5.7: Pulling from library/mysql bf5952930446: Already exists 8254623a9871: Already exists 938e3e06dac4: Already exists ea28ebf28884: Already exists f3cef38785c2: Already exists 894f9792565a: Already exists 1d8a57523420: Already exists 5f09bf1d31c1: Pull complete 1b6ff254abe7: Pull complete 74310a0bf42d: Pull complete d398726627fd: Pull complete Digest: sha256:da58f943b94721d46e87d5de208dc07302a8b13e638cd1d24285d222376d6d84 Status: Downloaded newer image for mysql:5.7 docker.io/library/mysql:5.7 # 查看本地鏡像 [root@iZ2zeg4ytp0whqtmxbsqiiZ ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mysql 5.7 718a6da099d8 6 days ago 448MB mysql latest 0d64f46acfd1 6 days ago 544MB hello-world latest bf756fb1ae65 7 months ago 13.3kB
docker rmi 刪除鏡像
[root@iZ2zeg4ytp0whqtmxbsqiiZ ~]# docker rmi -f IMAGE ID # 刪除指定鏡像 [root@iZ2zeg4ytp0whqtmxbsqiiZ ~]# docker rmi -f IMAGE ID1 IMAGE ID2 IMAGE ID3 # 刪除多個鏡像 [root@iZ2zeg4ytp0whqtmxbsqiiZ ~]# docker rmi -f $(docker images -aq) # 刪除所有鏡像
容器命令
說明: 我們有了鏡像纔可創建容器,linux,下載一個centos鏡像來測試學習
docker pull centos
新建容器並啓動
docker run [可選參數] image # 參數說明 --name=“Name” 容器名字 tomcat01 tomcat02 用來區分容器 -d 後臺方式運行 -it 使用交互方式運行,進入容器查看內容 -p 指定容器的端口 -p 8080:8080 -p ip:主機端口:容器端口 -p 主機端口:容器端口(常用) -p 容器端口 容器端口 -p 隨機指定端口 # 測試,啓動並進入容器 [root@iZ2zeg4ytp0whqtmxbsqiiZ ~]# docker run -it centos /bin/bash [root@74e82b7980e7 /]# ls # 查看容器內的centos,基礎版本,很多命令是不完善的 bin etc lib lost+found mnt proc run srv tmp var dev home lib64 media opt root sbin sys usr # 從容器中退回主機 [root@77969f5dcbf9 /]# exit exit [root@iZ2zeg4ytp0whqtmxbsqiiZ /]# ls bin dev fanfan lib lost+found mnt proc run srv tmp var boot etc home lib64 media opt root sbin sys usr
列出所有的運行的容器
# docker ps 命令 # 列出當前正在運行的容器 -a # 列出正在運行的容器包括歷史容器 -n=? # 顯示最近創建的容器 -q # 只顯示當前容器的編號 [root@iZ2zeg4ytp0whqtmxbsqiiZ /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@iZ2zeg4ytp0whqtmxbsqiiZ /]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 77969f5dcbf9 centos "/bin/bash" 5 minutes ago Exited (0) 5 minutes ago xenodochial_bose 74e82b7980e7 centos "/bin/bash" 16 minutes ago Exited (0) 6 minutes ago silly_cori a57250395804 bf756fb1ae65 "/hello" 7 hours ago Exited (0) 7 hours ago elated_nash 392d674f4f18 bf756fb1ae65 "/hello" 8 hours ago Exited (0) 8 hours ago distracted_mcnulty 571d1bc0e8e8 bf756fb1ae65 "/hello" 23 hours ago Exited (0) 23 hours ago magical_burnell [root@iZ2zeg4ytp0whqtmxbsqiiZ /]# docker ps -qa 77969f5dcbf9 74e82b7980e7 a57250395804 392d674f4f18 571d1bc0e8e8
退出容器
exit # 直接退出容器並關閉
Ctrl + P + Q # 容器不關閉退出
刪除容器
docker rm -f 容器id # 刪除指定容器
docker rm -f $(docker ps -aq) # 刪除所有容器
docker ps -a -q|xargs docker rm -f # 刪除所有的容器
啓動和停止容器的操作
docker start 容器id # 啓動容器
docker restart 容器id # 重啓容器
docker stop 容器id # 停止當前正在運行的容器
docker kill 容器id # 強制停止當前的容器
常用的其他命令
後臺啓動容器
# 命令 docker run -d 鏡像名 [root@iZ2zeg4ytp0whqtmxbsqiiZ /]# docker run -d centos # 問題 docker ps, 發現centos停止了 # 常見的坑, docker 容器使用後臺運行, 就必須要有一個前臺進程,docker發現沒有應用,就會自動停止 # nginx, 容器啓動後,發現自己沒有提供服務,就會立即停止,就是沒有程序了
查看日誌
docker logs -tf --tail number 容器id [root@iZ2zeg4ytp0whqtmxbsqiiZ /]# docker logs -tf --tail 1 8d1621e09bff 2020-08-11T10:53:15.987702897Z [root@8d1621e09bff /]# exit # 日誌輸出 # 自己編寫一段shell腳本 [root@iZ2zeg4ytp0whqtmxbsqiiZ /]# docker run -d centos /bin/sh -c "while true;do echo xiaofan;sleep 1;done" a0d580a21251da97bc050763cf2d5692a455c228fa2a711c3609872008e654c2 [root@iZ2zeg4ytp0whqtmxbsqiiZ /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a0d580a21251 centos "/bin/sh -c 'while t…" 3 seconds ago Up 1 second lucid_black # 顯示日誌 -tf # 顯示日誌 --tail number # 顯示日誌條數 [root@iZ2zeg4ytp0whqtmxbsqiiZ /]# docker logs -tf --tail 10 a0d580a21251
查看容器中進程信息ps
# 命令 docker top 容器id [root@iZ2zeg4ytp0whqtmxbsqiiZ /]# docker top df358bc06b17 UID PID PPID C STIME TTY root 28498 28482 0 19:38 ?
查看鏡像的元數據
# 命令 docker inspect 容器id [root@iZ2zeg4ytp0whqtmxbsqiiZ /]# docker inspect df358bc06b17 [ { "Id": "df358bc06b17ef44f215d35d9f46336b28981853069a3739edfc6bd400f99bf3", "Created": "2020-08-11T11:38:34.935048603Z", "Path": "/bin/bash", "Args": [], "State": { "Status": "running", "Running": true, "Paused": false, "Restarting": false, "OOMKilled": false, "Dead": false, "Pid": 28498, "ExitCode": 0, "Error": "", "StartedAt": "2020-08-11T11:38:35.216616071Z", "FinishedAt": "0001-01-01T00:00:00Z" }, "Image": "sha256:0d120b6ccaa8c5e149176798b3501d4dd1885f961922497cd0abef155c869566", "ResolvConfPath": "/var/lib/docker/containers/df358bc06b17ef44f215d35d9f46336b28981853069a3739edfc6bd400f99bf3/resolv.conf", "HostnamePath": "/var/lib/docker/containers/df358bc06b17ef44f215d35d9f46336b28981853069a3739edfc6bd400f99bf3/hostname", "HostsPath": "/var/lib/docker/containers/df358bc06b17ef44f215d35d9f46336b28981853069a3739edfc6bd400f99bf3/hosts", "LogPath": "/var/lib/docker/containers/df358bc06b17ef44f215d35d9f46336b28981853069a3739edfc6bd400f99bf3/df358bc06b17ef44f215d35d9f46336b28981853069a3739edfc6bd400f99bf3-json.log", "Name": "/hungry_heisenberg", "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, "Capabilities": null, "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/5af8a2aadbdba9e1e066331ff4bce56398617710a22ef906f9ce4d58bde2d360-init/diff:/var/lib/docker/overlay2/62926d498bd9d1a6684bb2f9920fb77a2f88896098e66ef93c4b74fcb19f29b6/diff", "MergedDir": "/var/lib/docker/overlay2/5af8a2aadbdba9e1e066331ff4bce56398617710a22ef906f9ce4d58bde2d360/merged", "UpperDir": "/var/lib/docker/overlay2/5af8a2aadbdba9e1e066331ff4bce56398617710a22ef906f9ce4d58bde2d360/diff", "WorkDir": "/var/lib/docker/overlay2/5af8a2aadbdba9e1e066331ff4bce56398617710a22ef906f9ce4d58bde2d360/work" }, "Name": "overlay2" }, "Mounts": [], "Config": { "Hostname": "df358bc06b17", "Domainname": "", "User": "", "AttachStdin": true, "AttachStdout": true, "AttachStderr": true, "Tty": true, "OpenStdin": true, "StdinOnce": true, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/bash" ], "Image": "centos", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": { "org.label-schema.build-date": "20200809", "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": "4822f9ac2058e8415ebefbfa73f05424fe20cc8280a5720ad3708fa6e80cdb08", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": {}, "SandboxKey": "/var/run/docker/netns/4822f9ac2058", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "5fd269c0a28227241e40cd30658e3ffe8ad6cc3e6514917c867d89d36a31d605", "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": "30d6017888627cb565618b1639fecf8fc97e1ae4df5a9fd5ddb046d8fb02b565", "EndpointID": "5fd269c0a28227241e40cd30658e3ffe8ad6cc3e6514917c867d89d36a31d605", "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 } } } } ] [root@iZ2zeg4ytp0whqtmxbsqiiZ /]#
進入當前正在運行的容器
# 我們通常容器使用後臺方式運行的, 需要進入容器,修改一些配置 # 命令 docker exec -it 容器id /bin/bash # 測試 [root@iZ2zeg4ytp0whqtmxbsqiiZ /]# docker exec -it df358bc06b17 /bin/bash [root@df358bc06b17 /]# ls bin etc lib lost+found mnt proc run srv tmp var dev home lib64 media opt root sbin sys usr [root@df358bc06b17 /]# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 Aug11 pts/0 00:00:00 /bin/bash root 29 0 0 01:06 pts/1 00:00:00 /bin/bash root 43 29 0 01:06 pts/1 00:00:00 ps -ef # 方式二 docker attach 容器id # docker exec # 進入容器後開啓一個新的終端,可以在裏面操作 # docker attach # 進入容器正在執行的終端,不會啓動新的進程
從容器中拷貝文件到主機
docker cp 容器id:容器內路徑 目的地主機路徑
[root@iZ2zeg4ytp0whqtmxbsqiiZ /]# docker cp 7af535f807e0:/home/Test.java /home
進入當前正在運行的容器
我們通常容器都是使用後臺方式運行的,需要進入容器,修改一些配置
命令
docker exec -it 容器id bashshell
#測試
➜ ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
55321bcae33d centos “/bin/sh -c 'while t…” 10 minutes ago Up 10 minutes bold_bell
a7215824a4db centos “/bin/sh -c 'while t…” 13 minutes ago Up 13 minutes zen_kepler
55a31b3f8613 centos “/bin/bash” 15 minutes ago Up 15 minutes lucid_clarke
➜ ~ docker exec -it 55321bcae33d /bin/bash
[root@55321bcae33d /]#
# 方式二
docker attach 容器id
#測試
docker attach 55321bcae33d
正在執行當前的代碼...
區別
#docker exec #進入當前容器後開啓一個新的終端,可以在裏面操作。(常用)
#docker attach # 進入容器正在執行的終端
從容器內拷貝到主機上
docker cp 容器id:容器內路徑 主機目的路徑 [root@iz2zeak7sgj6i7hrb2g862z ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 56a5583b25b4 centos "/bin/bash" 7seconds ago Up 6 seconds #1. 進入docker容器內部 [root@iz2zeak7sgj6i7hrb2g862z ~]# docker exec -it 56a5583b25b4 /bin/bash [root@55321bcae33d /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var #新建一個文件 [root@55321bcae33d /]# echo "hello" > java.java [root@55321bcae33d /]# cat hello.java hello [root@55321bcae33d /]# exit exit #hello.java拷貝到home文件加下 [root@iz2zeak7sgj6i7hrb2g862z /]# docker cp 56a5583b25b4:/hello.java /home [root@iz2zeak7sgj6i7hrb2g862z /]# cd /home [root@iz2zeak7sgj6i7hrb2g862z home]# ls -l #可以看見java.java存在 total 8 -rw-r--r-- 1 root root 0 May 19 22:09 haust.java -rw-r--r-- 1 root root 6 May 22 11:12 java.java drwx------ 3 www www 4096 May 8 12:14 www
學習方式:將我的所有筆記敲一遍,自己記錄筆記!
命令大全
attach Attach local standard input, output, and error streams to a running container #當前shell下 attach連接指定運行的鏡像 build Build an image from a Dockerfile # 通過Dockerfile定製鏡像 commit Create a new image from a container's changes #提交當前容器爲新的鏡像 cp Copy files/folders between a container and the local filesystem #拷貝文件 create Create a new container #創建一個新的容器 diff Inspect changes to files or directories on a container's filesystem #查看docker容器的變化 events Get real time events from the server # 從服務獲取容器實時時間 exec Run a command in a running container # 在運行中的容器上運行命令 export Export a container's filesystem as a tar archive #導出容器文件系統作爲一個tar歸檔文件[對應import] history Show the history of an image # 展示一個鏡像形成歷史 images List images #列出系統當前的鏡像 import Import the contents from a tarball to create a filesystem image #從tar包中導入內容創建一個文件系統鏡像 info Display system-wide information # 顯示全系統信息 inspect Return low-level information on Docker objects #查看容器詳細信息 kill Kill one or more running containers # kill指定docker容器 load Load an image from a tar archive or STDIN #從一個tar包或標準輸入中加載一個鏡像[對應save] login Log in to a Docker registry # logout Log out from a Docker registry logs Fetch the logs of a container pause Pause all processes within one or more containers port List port mappings or a specific mapping for the container ps List containers pull Pull an image or a repository from a registry push Push an image or a repository to a registry rename Rename a container restart Restart one or more containers rm Remove one or more containers rmi Remove one or more images run Run a command in a new container save Save one or more images to a tar archive (streamed to STDOUT by default) search Search the Docker Hub for images start Start one or more stopped containers stats Display a live stream of container(s) resource usage statistics stop Stop one or more running containers tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE top Display the running processes of a container unpause Unpause all processes within one or more containers update Update configuration of one or more containers version Show the Docker version information wait Block until one or more containers stop, then print their exit codes
作業練習
作業一:Docker 安裝Nginx
#1. 搜索鏡像 search 建議大家去docker搜索,可以看到幫助文檔 [root@iz2zeak7sgj6i7hrb2g862z ~]# docker search nginx #2. 拉取下載鏡像 pull [root@iz2zeak7sgj6i7hrb2g862z ~]# docker pull nginx #3. 查看是否下載成功鏡像 [root@iz2zeak7sgj6i7hrb2g862z ~]# docker images #3. 運行測試 # -d 後臺運行 # --name 給容器命名 # -p 宿主機端口:容器內部端口 [root@iz2zeak7sgj6i7hrb2g862z ~]# docker run -d --name nginx01 -p 3344:80 nginx aa664b0c8ed98f532453ce1c599be823bcc1f3c9209e5078615af416ccb454c2 #4. 查看正在啓動的鏡像 [root@iz2zeak7sgj6i7hrb2g862z ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 75943663c116 nginx "nginx -g 'daemon of…" 41 seconds ago Up 40 seconds 0.0.0.0:82->80/tcp nginx00 #5. 進入容器 [root@iz2zeak7sgj6i7hrb2g862z ~]# docker exec -it nginx01 /bin/bash #進入 root@aa664b0c8ed9:/# whereis nginx #找到nginx位置 nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx root@aa664b0c8ed9:/# cd /etc/nginx/ root@aa664b0c8ed9:/etc/nginx# ls conf.d fastcgi_params koi-utf koi-win mime.types modules nginx.conf scgi_params uwsgi_params win-utf #6. 退出容器 root@aa664b0c8ed9:/etc/nginx# exit exit #7. 停止容器 [root@iz2zeak7sgj6i7hrb2g862z ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES aa664b0c8ed9 nginx "nginx -g 'daemon of…" 10 minutes ago Up 10 minutes 0.0.0.0:3344->80/tcp nginx01 [root@iz2zeak7sgj6i7hrb2g862z ~]# docker stop aa664b0c8ed9
宿主機端口 和 容器內部端口 以及端口暴露:
**問題:**我們每次改動nginx配置文件,都需要進入容器內部?十分麻煩,我要是可以在容器外部提供一個映射路徑,達到在容器外部修改文件名,容器內部就可以自動修改?-v 數據卷 技術!
作業二:用docker 來裝一個tomcat
# 下載 tomcat9.0 # 之前的啓動都是後臺,停止了容器,容器還是可以查到, docker run -it --rm 鏡像名 一般是用來測試,用完就刪除 [root@iz2zeak7sgj6i7hrb2g862z ~]# docker run -it --rm tomcat:9.0 --rm Automatically remove the container when it exits 用完即刪 #下載 最新版 [root@iz2zeak7sgj6i7hrb2g862z ~]# docker pull tomcat #查看下載的鏡像 [root@iz2zeak7sgj6i7hrb2g862z ~]# docker images #以後臺方式,暴露端口方式,啓動運行 [root@iz2zeak7sgj6i7hrb2g862z ~]# docker run -d -p 8080:8080 --name tomcat01 tomcat #測試訪問有沒有問題 curl localhost:8080 #根據容器id進入tomcat容器 [root@iz2zeak7sgj6i7hrb2g862z ~]# docker exec -it 645596565d3f /bin/bash root@645596565d3f:/usr/local/tomcat# #查看tomcat容器內部內容: root@645596565d3f:/usr/local/tomcat# ls -l total 152 -rw-r--r-- 1 root root 18982 May 5 20:40 BUILDING.txt -rw-r--r-- 1 root root 5409 May 5 20:40 CONTRIBUTING.md -rw-r--r-- 1 root root 57092 May 5 20:40 LICENSE -rw-r--r-- 1 root root 2333 May 5 20:40 NOTICE -rw-r--r-- 1 root root 3255 May 5 20:40 README.md -rw-r--r-- 1 root root 6898 May 5 20:40 RELEASE-NOTES -rw-r--r-- 1 root root 16262 May 5 20:40 RUNNING.txt drwxr-xr-x 2 root root 4096 May 16 12:05 bin drwxr-xr-x 1 root root 4096 May 21 11:04 conf drwxr-xr-x 2 root root 4096 May 16 12:05 lib drwxrwxrwx 1 root root 4096 May 21 11:04 logs drwxr-xr-x 2 root root 4096 May 16 12:05 native-jni-lib drwxrwxrwx 2 root root 4096 May 16 12:05 temp drwxr-xr-x 2 root root 4096 May 16 12:05 webapps drwxr-xr-x 7 root root 4096 May 5 20:37 webapps.dist drwxrwxrwx 2 root root 4096 May 5 20:36 work root@645596565d3f:/usr/local/tomcat# #進入webapps目錄 root@645596565d3f:/usr/local/tomcat# cd webapps root@645596565d3f:/usr/local/tomcat/webapps# ls root@645596565d3f:/usr/local/tomcat/webapps# # 發現問題:1、linux命令少了。 2.webapps目錄爲空 # 原因:阿里雲鏡像的原因,阿里雲默認是最小的鏡像,所以不必要的都剔除掉 # 保證最小可運行的環境! # 解決方案: # 將webapps.dist下的文件都拷貝到webapps下即可 root@645596565d3f:/usr/local/tomcat# ls 找到webapps.dist BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work root@645596565d3f:/usr/local/tomcat# cd webapps.dist/ # 進入webapps.dist root@645596565d3f:/usr/local/tomcat/webapps.dist# ls # 查看內容 ROOT docs examples host-manager manager root@645596565d3f:/usr/local/tomcat/webapps.dist# cd .. root@645596565d3f:/usr/local/tomcat# cp -r webapps.dist/* webapps # 拷貝webapps.dist 內容給webapps root@645596565d3f:/usr/local/tomcat# cd webapps #進入webapps root@645596565d3f:/usr/local/tomcat/webapps# ls #查看拷貝結果 ROOT docs examples host-manager manager
這樣docker部署tomcat就可以訪問了
問題:我們以後要部署項目,如果每次都要進入容器是不是十分麻煩?要是可以在容器外部提供一個映射路徑,比如webapps,我們在外部放置項目,就自動同步內部就好了!
作業三:部署elasticsearch+kibana
# es 暴露的端口很多! # es 十分耗內存 # es 的數據一般需要放置到安全目錄!掛載 # --net somenetwork ? 網絡配置 # 啓動elasticsearch [root@iz2zeak7sgj6i7hrb2g862z ~]# docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2 # 測試一下es是否成功啓動 ➜ ~ curl localhost:9200 { "name" : "d73ad2f22dd3", "cluster_name" : "docker-cluster", "cluster_uuid" : "atFKgANxS8CzgIyCB8PGxA", "version" : { "number" : "7.6.2", "build_flavor" : "default", "build_type" : "docker", "build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f", "build_date" : "2020-03-26T06:34:37.794943Z", "build_snapshot" : false, "lucene_version" : "8.4.0", "minimum_wire_compatibility_version" : "6.8.0", "minimum_index_compatibility_version" : "6.0.0-beta1" }, "tagline" : "You Know, for Search" } #測試成功就關掉elasticSearch,防止耗內存 [root@iz2zeak7sgj6i7hrb2g862z ~]# docker stop d834ce2bd306 d834ce2bd306 [root@iz2zeak7sgj6i7hrb2g862z ~]# docker stats # 查看docker容器使用內存情況
#測試成功就關掉elasticSearch,可以添加內存的限制,修改配置文件 -e 環境配置修改
➜ ~ docker rm -f d73ad2f22dd3 # stop命令也行
➜ ~ docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
➜ ~ curl localhost:9200 { "name" : "b72c9847ec48", "cluster_name" : "docker-cluster", "cluster_uuid" : "yNAK0EORSvq3Wtaqe2QqAg", "version" : { "number" : "7.6.2", "build_flavor" : "default", "build_type" : "docker", "build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f", "build_date" : "2020-03-26T06:34:37.794943Z", "build_snapshot" : false, "lucene_version" : "8.4.0", "minimum_wire_compatibility_version" : "6.8.0", "minimum_index_compatibility_version" : "6.0.0-beta1" }, "tagline" : "You Know, for Search" }
作業三:使用kibana連接es (elasticSearch)?思考網絡如何才能連接
Portainer 可視化面板安裝
- portainer(先用這個)
docker run -d -p 8080:9000 \ --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
- Rancher(CI/CD再用)
什麼是portainer?
Docker圖形化界面管理工具!提供一個後臺面板供我們操作!
# 安裝命令 [root@iz2zeak7sgj6i7hrb2g862z ~]# docker run -d -p 8080:9000 \ > --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer Unable to find image 'portainer/portainer:latest' locally latest: Pulling from portainer/portainer d1e017099d17: Pull complete a7dca5b5a9e8: Pull complete Digest: sha256:4ae7f14330b56ffc8728e63d355bc4bc7381417fa45ba0597e5dd32682901080 Status: Downloaded newer image for portainer/portainer:latest 81753869c4fd438cec0e31659cbed0d112ad22bbcfcb9605483b126ee8ff306d
測試訪問: 外網:8080 :http://123.56.247.59:8080/
進入之後的面板
鏡像原理之聯合文件系統
分層理解
分層的鏡像
我們可以去下載一個鏡像,注意觀察下載的日誌輸出,可以看到是一層層的在下載
思考:爲什麼Docker鏡像要採用這種分層的結構呢?
最大的好處,我覺得莫過於資源共享了!比如有多個鏡像都從相同的Base鏡像構建而來,那麼宿主機只需在磁盤上保留一份base鏡像,同時內存中也只需要加載一份base鏡像,這樣就可以爲所有的容器服務了,而且鏡像的每一層都可以被共享。
查看鏡像分層的方式可以通過docker image inspect 命令
➜ / docker image inspect redis [ { "Id": "sha256:f9b9909726890b00d2098081642edf32e5211b7ab53563929a47f250bcdc1d7c", "RepoTags": [ "redis:latest" ], "RepoDigests": [ "redis@sha256:399a9b17b8522e24fbe2fd3b42474d4bb668d3994153c4b5d38c3dafd5903e32" ], "Parent": "", "Comment": "", "Created": "2020-05-02T01:40:19.112130797Z", "Container": "d30c0bcea88561bc5139821227d2199bb027eeba9083f90c701891b4affce3bc", "ContainerConfig": { "Hostname": "d30c0bcea885", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "ExposedPorts": { "6379/tcp": {} }, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "GOSU_VERSION=1.12", "REDIS_VERSION=6.0.1", "REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.0.1.tar.gz", "REDIS_DOWNLOAD_SHA=b8756e430479edc162ba9c44dc89ac394316cd482f2dc6b91bcd5fe12593f273" ], "Cmd": [ "/bin/sh", "-c", "#(nop) ", "CMD [\"redis-server\"]" ], "ArgsEscaped": true, "Image": "sha256:704c602fa36f41a6d2d08e49bd2319ccd6915418f545c838416318b3c29811e0", "Volumes": { "/data": {} }, "WorkingDir": "/data", "Entrypoint": [ "docker-entrypoint.sh" ], "OnBuild": null, "Labels": {} }, "DockerVersion": "18.09.7", "Author": "", "Config": { "Hostname": "", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "ExposedPorts": { "6379/tcp": {} }, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "GOSU_VERSION=1.12", "REDIS_VERSION=6.0.1", "REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.0.1.tar.gz", "REDIS_DOWNLOAD_SHA=b8756e430479edc162ba9c44dc89ac394316cd482f2dc6b91bcd5fe12593f273" ], "Cmd": [ "redis-server" ], "ArgsEscaped": true, "Image": "sha256:704c602fa36f41a6d2d08e49bd2319ccd6915418f545c838416318b3c29811e0", "Volumes": { "/data": {} }, "WorkingDir": "/data", "Entrypoint": [ "docker-entrypoint.sh" ], "OnBuild": null, "Labels": null }, "Architecture": "amd64", "Os": "linux", "Size": 104101893, "VirtualSize": 104101893, "GraphDriver": { "Data": { "LowerDir": "/var/lib/docker/overlay2/adea96bbe6518657dc2d4c6331a807eea70567144abda686588ef6c3bb0d778a/diff:/var/lib/docker/overlay2/66abd822d34dc6446e6bebe73721dfd1dc497c2c8063c43ffb8cf8140e2caeb6/diff:/var/lib/docker/overlay2/d19d24fb6a24801c5fa639c1d979d19f3f17196b3c6dde96d3b69cd2ad07ba8a/diff:/var/lib/docker/overlay2/a1e95aae5e09ca6df4f71b542c86c677b884f5280c1d3e3a1111b13644b221f9/diff:/var/lib/docker/overlay2/cd90f7a9cd0227c1db29ea992e889e4e6af057d9ab2835dd18a67a019c18bab4/diff", "MergedDir": "/var/lib/docker/overlay2/afa1de233453b60686a3847854624ef191d7bc317fb01e015b4f06671139fb11/merged", "UpperDir": "/var/lib/docker/overlay2/afa1de233453b60686a3847854624ef191d7bc317fb01e015b4f06671139fb11/diff", "WorkDir": "/var/lib/docker/overlay2/afa1de233453b60686a3847854624ef191d7bc317fb01e015b4f06671139fb11/work" }, "Name": "overlay2" }, "RootFS": { "Type": "layers", "Layers": [ "sha256:c2adabaecedbda0af72b153c6499a0555f3a769d52370469d8f6bd6328af9b13", "sha256:744315296a49be711c312dfa1b3a80516116f78c437367ff0bc678da1123e990", "sha256:379ef5d5cb402a5538413d7285b21aa58a560882d15f1f553f7868dc4b66afa8", "sha256:d00fd460effb7b066760f97447c071492d471c5176d05b8af1751806a1f905f8", "sha256:4d0c196331523cfed7bf5bafd616ecb3855256838d850b6f3d5fba911f6c4123", "sha256:98b4a6242af2536383425ba2d6de033a510e049d9ca07ff501b95052da76e894" ] }, "Metadata": { "LastTagTime": "0001-01-01T00:00:00Z" } } ]
理解:
所有的 Docker鏡像都起始於一個基礎鏡像層,當進行修改或培加新的內容時,就會在當前鏡像層之上,創建新的鏡像層。
舉一個簡單的例子,假如基於 Ubuntu Linux16.04創建一個新的鏡像,這就是新鏡像的第一層;如果在該鏡像中添加 Python包,
就會在基礎鏡像層之上創建第二個鏡像層;如果繼續添加一個安全補丁,就會創健第三個鏡像層該像當前已經包含3個鏡像層,如下圖所示(這只是一個用於演示的很簡單的例子)。
在添加額外的鏡像層的同時,鏡像始終保持是當前所有鏡像的組合,理解這一點.
在添加額外的鏡像層的同時,鏡像始終保持是當前所有鏡像的組合,理解這一點非常重要。下圖中舉了一個簡單的例子,每個鏡像層包含3個文件,而鏡像包含了來自兩個鏡像層的6個文件。
上圖中的鏡像層跟之前圖中的略有區別,主要目的是便於展示文件
下圖中展示了一個稍微複雜的三層鏡像,在外部看來整個鏡像只有6個文件,這是因爲最上層中的文件7是文件5的一個更新版。
文種情況下,上層鏡像層中的文件覆蓋了底層鏡像層中的文件。這樣就使得文件的更新版本作爲一個新鏡像層添加到鏡像當中
Docker通過存儲引擎(新版本採用快照機制)的方式來實現鏡像層堆棧,並保證多鏡像層對外展示爲統一的文件系統
Linux上可用的存儲引撃有AUFS、 Overlay2、 Device Mapper、Btrfs以及ZFS。顧名思義,每種存儲引擎都基於 Linux中對應的
件系統或者塊設備技術,井且每種存儲引擎都有其獨有的性能特點。
Docker在 Windows上僅支持 windowsfilter 一種存儲引擎,該引擎基於NTFS文件系統之上實現了分層和CoW [1]。
下圖展示了與系統顯示相同的三層鏡像。所有鏡像層堆併合井,對外提供統一的視圖。
特點
Docker 鏡像都是隻讀的,當容器啓動時,一個新的可寫層加載到鏡像的頂部!
這一層就是我們通常說的容器層,容器之下的都叫鏡像層!
commit鏡像
docker commit 提交容器成爲一個新的副本
# 命令和git原理類似
docker commit -m="描述信息" -a="作者" 容器id 目標鏡像名:[版本TAG]
實戰測試
# 1、啓動一個默認的tomcat [root@iz2zeak7sgj6i7hrb2g862z ~]# docker run -d -p 8080:8080 tomcat de57d0ace5716d27d0e3a7341503d07ed4695ffc266aef78e0a855b270c4064e # 2、發現這個默認的tomcat 是沒有webapps應用,官方的鏡像默認webapps下面是沒有文件的! #docker exec -it 容器id /bin/bash [root@iz2zeak7sgj6i7hrb2g862z ~]# docker exec -it de57d0ace571 /bin/bash root@de57d0ace571:/usr/local/tomcat# # 3、從webapps.dist拷貝文件進去webapp root@de57d0ace571:/usr/local/tomcat# cp -r webapps.dist/* webapps root@de57d0ace571:/usr/local/tomcat# cd webapps root@de57d0ace571:/usr/local/tomcat/webapps# ls ROOT docs examples host-manager manager # 4、將操作過的容器通過commit調教爲一個鏡像!我們以後就使用我們修改過的鏡像即可,而不需要每次都重新拷貝webapps.dist下的文件到webapps了,這就是我們自己的一個修改的鏡像。 docker commit -m="描述信息" -a="作者" 容器id 目標鏡像名:[TAG] docker commit -a="kuangshen" -m="add webapps app" 容器id tomcat02:1.0 [root@iz2zeak7sgj6i7hrb2g862z ~]# docker commit -a="csp提交的" -m="add webapps app" de57d0ace571 tomcat02.1.0 sha256:d5f28a0bb0d0b6522fdcb56f100d11298377b2b7c51b9a9e621379b01cf1487e [root@iz2zeak7sgj6i7hrb2g862z ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE tomcat02.1.0 latest d5f28a0bb0d0 14 seconds ago 652MB tomcat latest 1b6b1fe7261e 5 days ago 647MB nginx latest 9beeba249f3e 5 days ago 127MB mysql 5.7 b84d68d0a7db 5 days ago 448MB elasticsearch 7.6.2 f29a1ee41030 8 weeks ago 791MB portainer/portainer latest 2869fc110bf7 2 months ago 78.6MB centos latest 470671670cac 4 months ago 237MB hello-world latest bf756fb1ae65 4 months ago 13.3kB
容器數據卷
什麼是容器數據卷
將應用和環境打包成一個鏡像!
數據?如果數據都在容器中,那麼我們容器刪除,數據就會丟失!需求:數據可以持久化
MySQL,容器刪除了,刪庫跑路!需求:MySQL數據可以存儲在本地!
容器之間可以有一個數據共享的技術!Docker容器中產生的數據,同步到本地!
這就是卷技術!目錄的掛載,將我們容器內的目錄,掛載到Linux上面!
總結一句話:容器的持久化和同步操作!容器間也是可以數據共享的!
使用數據卷
方式一 :直接使用命令掛載 -v
-v, --volume list Bind mount a volume docker run -it -v 主機目錄:容器內目錄 -p 主機端口:容器內端口 # /home/ceshi:主機home目錄下的ceshi文件夾 映射:centos容器中的/home [root@iz2zeak7 home]# docker run -it -v /home/ceshi:/home centos /bin/bash #這時候主機的/home/ceshi文件夾就和容器的/home文件夾關聯了,二者可以實現文件或數據同步了 #通過 docker inspect 容器id 查看 [root@iz2zeak7sgj6i7hrb2g862z home]# docker inspect 6064c490c371
測試文件的同步
再來測試!
1、停止容器
2、宿主機修改文件
3、啓動容器
4、容器內的數據依舊是同步的
好處:我們以後修改只需要在本地修改即可,容器內會自動同步!
實戰:安裝MySQL
思考:MySQL的數據持久化的問題
# 獲取mysql鏡像 [root@iz2zeak7sgj6i7hrb2g862z home]# docker pull mysql:5.7 # 運行容器,需要做數據掛載 #安裝啓動mysql,需要配置密碼的,這是要注意點! # 參考官網hub docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag #啓動我們得 -d 後臺運行 -p 端口映射 -v 卷掛載 -e 環境配置 -- name 容器名字 $ docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql03 mysql:5.7 # 啓動成功之後,我們在本地使用sqlyog來測試一下 # sqlyog-連接到服務器的3306--和容器內的3306映射 # 在本地測試創建一個數據庫,查看一下我們映射的路徑是否ok!
測試連接:注意3310端口要在阿里雲服務器的安全組中打開,否則無法連接。
當我們在本地用SQLyog新建名稱爲test的數據庫時候,容器容器也會創建
假設我們將包含mysql的容器刪除時,
發現,我們掛載到本地的數據卷依舊沒有丟失,這就實現了容器數據持久化功能。
具名和匿名掛載
# 匿名掛載 -v 容器內路徑! $ docker run -d -P --name nginx01 -v /etc/nginx nginx # 查看所有的volume(卷)的情況 $ docker volume ls DRIVER VOLUME NAME # 容器內的卷名(匿名卷掛載) local 21159a8518abd468728cdbe8594a75b204a10c26be6c36090cde1ee88965f0d0 local b17f52d38f528893dd5720899f555caf22b31bf50b0680e7c6d5431dbda2802c # 這裏發現,這種就是匿名掛載,我們在 -v只寫了容器內的路徑,沒有寫容器外的路徑! # 具名掛載 -P:表示隨機映射端口 $ docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx 9663cfcb1e5a9a1548867481bfddab9fd7824a6dc4c778bf438a040fe891f0ee # 查看所有的volume(卷)的情況 $ docker volume ls DRIVER VOLUME NAME local 21159a8518abd468728cdbe8594a75b204a10c26be6c36090cde1ee88965f0d0 local b17f52d38f528893dd5720899f555caf22b31bf50b0680e7c6d5431dbda2802c local juming-nginx #多了一個名字 # 通過 -v 卷名:查看容器內路徑 # 查看一下這個卷 $ docker volume inspect juming-nginx [ { "CreatedAt": "2020-05-23T13:55:34+08:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data", #默認目錄 "Name": "juming-nginx", "Options": null, "Scope": "local" } ]
所有的docker容器內的卷,沒有指定目錄的情況下都是在**/var/lib/docker/volumes/自定義的卷名/_data**下,
如果指定了目錄,docker volume ls 是查看不到的。
區分三種掛載方式
# 三種掛載: 匿名掛載、具名掛載、指定路徑掛載
-v 容器內路徑 #匿名掛載
-v 卷名:容器內路徑 #具名掛載
-v /宿主機路徑:容器內路徑 #指定路徑掛載 docker volume ls 是查看不到的
拓展:
# 通過 -v 容器內路徑: ro rw 改變讀寫權限
ro #readonly 只讀
rw #readwrite 可讀可寫
$ docker run -d -P --name nginx05 -v juming:/etc/nginx:ro nginx
$ docker run -d -P --name nginx05 -v juming:/etc/nginx:rw nginx
# ro 只要看到ro就說明這個路徑只能通過宿主機來操作,容器內部是無法操作!
初始Dockerfile
Dockerfile 就是用來構建docker鏡像的構建文件!命令腳本!先體驗一下!
通過這個腳本可以生成鏡像,鏡像是一層一層的,腳本是一個個的命令,每個命令都是一層!
# 創建一個dockerfile文件,名字可以隨便 建議Dockerfile # 文件中的內容: 指令(大寫) + 參數 $ vim dockerfile1 FROM centos # 當前這個鏡像是以centos爲基礎的 VOLUME ["volume01","volume02"] # 掛載卷的卷目錄列表(多個目錄) CMD echo "-----end-----" # 輸出一下用於測試 CMD /bin/bash # 默認走bash控制檯 # 這裏的每個命令,就是鏡像的一層! # 構建出這個鏡像 -f dockerfile1 # f代表file,指這個當前文件的地址(這裏是當前目錄下的dockerfile1) -t caoshipeng/centos # t就代表target,指目標目錄(注意caoshipeng鏡像名前不能加斜槓‘/’) . # 表示生成在當前目錄下 $ docker build -f dockerfile1 -t caoshipeng/centos . Sending build context to Docker daemon 2.56kB Step 1/4 : FROM centos latest: Pulling from library/centos 8a29a15cefae: Already exists Digest: sha256:fe8d824220415eed5477b63addf40fb06c3b049404242b31982106ac204f6700 Status: Downloaded newer image for centos:latest ---> 470671670cac Step 2/4 : VOLUME ["volume01","volume02"] # 卷名列表 ---> Running in c18eefc2c233 Removing intermediate container c18eefc2c233 ---> 623ae1d40fb8 Step 3/4 : CMD echo "-----end-----" # 輸出 腳本命令 ---> Running in 70e403669f3c Removing intermediate container 70e403669f3c ---> 0eba1989c4e6 Step 4/4 : CMD /bin/bash ---> Running in 4342feb3a05b Removing intermediate container 4342feb3a05b ---> f4a6b0d4d948 Successfully built f4a6b0d4d948 Successfully tagged caoshipeng/centos:latest # 查看自己構建的鏡像 $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE caoshipeng/centos latest f4a6b0d4d948 About a minute ago 237MB
啓動自己寫的容器鏡像
$ docker run -it f4a6b0d4d948 /bin/bash # 運行自己寫的鏡像
$ ls -l # 查看目錄
這個卷和外部一定有一個同步的目錄
如果沒有找到掛載卷的位置可以手動再掛載一下
查看一下卷掛載
# docker inspect 容器id
$ docker inspect ca3b45913df5
測試一下剛纔的文件是否同步出去了!
這種方式使用的十分多,因爲我們通常會構建自己的鏡像!
假設構建鏡像時候沒有掛載卷,要手動鏡像掛載 -v 卷名:容器內路徑!
數據卷容器
多個MySQL同步數據!
命名的容器掛載數據卷!
# 測試 啓動3個容器,通過剛纔自己寫的鏡像啓動 # 創建docker01:因爲我本機是最新版,故這裏用latest,狂神老師用的是1.0如下圖 $ docker run -it --name docker01 caoshipeng/centos:latest # 查看容器docekr01內容 $ ls bin home lost+found opt run sys var dev lib media proc sbin tmp volume01 etc lib64 mnt root srv usr volume02 # 不關閉該容器退出 CTRL + Q + P # 創建docker02: 並且讓docker02 繼承 docker01 $ docker run -it --name docker02 --volumes-from docker01 caoshipeng/centos:latest # 查看容器docker02內容 $ ls bin home lost+found opt run sys var dev lib media proc sbin tmp volume01 etc lib64 mnt root srv usr volume02
# 再新建一個docker03同樣繼承docker01 $ docker run -it --name docker03 --volumes-from docker01 caoshipeng/centos:latest $ cd volume01 #進入volume01 查看是否也同步docker01的數據 $ ls docker01.txt # 測試:可以刪除docker01,查看一下docker02和docker03是否可以訪問這個文件 # 測試發現:數據依舊保留在docker02和docker03中沒有被刪除
$ 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 $ docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7 # 這個時候,可以實現兩個容器數據同步!
結論:
容器之間的配置信息的傳遞,數據卷容器的生命週期一直持續到沒有容器使用爲止。
但是一旦你持久化到了本地,這個時候,本地的數據是不會刪除的!
DockerFile
DockerFile介紹
dockerfile是用來構建docker鏡像的文件!命令參數腳本!
構建步驟:
1、 編寫一個dockerfile文件
2、 docker build 構建稱爲一個鏡像
3、 docker run運行鏡像
4、 docker push發佈鏡像(DockerHub 、阿里雲倉庫)
點擊後跳到一個Dockerfile
很多官方鏡像都是基礎包,很多功能沒有,我們通常會自己搭建自己的鏡像!
官方既然可以製作鏡像,那我們也可以!
DockerFile構建過程
基礎知識:
1、每個保留關鍵字(指令)都是必須是大寫字母
2、執行從上到下順序
3、#表示註釋
4、每一個指令都會創建提交一個新的鏡像曾,並提交!
Dockerfile是面向開發的,我們以後要發佈項目,做鏡像,就需要編寫dockerfile文件,這個文件十分簡單!
Docker鏡像逐漸成企業交付的標準,必須要掌握!
DockerFile:構建文件,定義了一切的步驟,源代碼
DockerImages:通過DockerFile構建生成的鏡像,最終發佈和運行產品。
Docker容器:容器就是鏡像運行起來提供服務。
DockerFile的指令
FROM # from:基礎鏡像,一切從這裏開始構建 MAINTAINER # maintainer:鏡像是誰寫的, 姓名+郵箱 RUN # run:鏡像構建的時候需要運行的命令 ADD # add:步驟,tomcat鏡像,這個tomcat壓縮包!添加內容 添加同目錄 WORKDIR # workdir:鏡像的工作目錄 VOLUME # volume:掛載的目錄 EXPOSE # expose:保留端口配置 CMD # cmd:指定這個容器啓動的時候要運行的命令,只有最後一個會生效,可被替代 ENTRYPOINT # entrypoint:指定這個容器啓動的時候要運行的命令,可以追加命令 ONBUILD # onbuild:當構建一個被繼承DockerFile這個時候就會運行onbuild的指令,觸發指令 COPY # copy:類似ADD,將我們文件拷貝到鏡像中 ENV # env:構建的時候設置環境變量!
實戰測試
scratch 鏡像
FROM scratch ADD centos-7-x86_64-docker.tar.xz / LABEL \ org.label-schema.schema-version="1.0" \ org.label-schema.name="CentOS Base Image" \ org.label-schema.vendor="CentOS" \ org.label-schema.license="GPLv2" \ org.label-schema.build-date="20200504" \ org.opencontainers.image.title="CentOS Base Image" \ org.opencontainers.image.vendor="CentOS" \ org.opencontainers.image.licenses="GPL-2.0-only" \ org.opencontainers.image.created="2020-05-04 00:00:00+01:00" CMD ["/bin/bash"]
Docker Hub 中 99%的鏡像都是從這個基礎鏡像過來的 FROM scratch,然後配置需要的軟件和配置來進行構建。
創建一個自己的centos
# 1./home下新建dockerfile目錄 $ mkdir dockerfile # 2. dockerfile目錄下新建mydockerfile-centos文件 $ vim mydockerfile-centos # 3.編寫Dockerfile配置文件 FROM centos # 基礎鏡像是官方原生的centos MAINTAINER cao<[email protected]> # 作者 ENV MYPATH /usr/local # 配置環境變量的目錄 WORKDIR $MYPATH # 將工作目錄設置爲 MYPATH RUN yum -y install vim # 給官方原生的centos 增加 vim指令 RUN yum -y install net-tools # 給官方原生的centos 增加 ifconfig命令 EXPOSE 80 # 暴露端口號爲80 CMD echo $MYPATH # 輸出下 MYPATH 路徑 CMD echo "-----end----" CMD /bin/bash # 啓動後進入 /bin/bash # 4.通過這個文件構建鏡像 # 命令: docker build -f 文件路徑 -t 鏡像名:[tag] . $ docker build -f mydockerfile-centos -t mycentos:0.1 . # 5.出現下圖後則構建成功
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE mycentos 0.1 cbf5110a646d 2 minutes ago 311MB # 6.測試運行 $ docker run -it mycentos:0.1 # 注意帶上版本號,否則每次都回去找最新版latest $ pwd /usr/local # 與Dockerfile文件中 WORKDIR 設置的 MYPATH 一致 $ vim # vim 指令可以使用 $ ifconfig # ifconfig 指令可以使用 # docker history 鏡像id 查看鏡像構建歷史步驟 $ docker history 鏡像id
我們可以列出本地進行的變更歷史
我們平時拿到一個鏡像,可以用 “docker history 鏡像id” 研究一下是什麼做的
CMD 和 ENTRYPOINT區別
CMD # 指定這個容器啓動的時候要運行的命令,只有最後一個會生效,可被替代。
ENTRYPOINT # 指定這個容器啓動的時候要運行的命令,可以追加命令
測試cmd
# 編寫dockerfile文件 $ vim dockerfile-test-cmd FROM centos CMD ["ls","-a"] # 啓動後執行 ls -a 命令 # 構建鏡像 $ docker build -f dockerfile-test-cmd -t cmd-test:0.1 . # 運行鏡像 $ docker run cmd-test:0.1 # 由結果可得,運行後就執行了 ls -a 命令 . .. .dockerenv bin dev etc home # 想追加一個命令 -l 成爲ls -al:展示列表詳細數據 $ docker run cmd-test:0.1 -l docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\": executable file not found in $PATH": unknown. ERRO[0000] error waiting for container: context canceled # cmd的情況下 -l 替換了CMD["ls","-l"] 而 -l 不是命令所以報錯
測試ENTRYPOINT
# 編寫dockerfile文件 $ vim dockerfile-test-entrypoint FROM centos ENTRYPOINT ["ls","-a"] # 構建鏡像 $ docker build -f dockerfile-test-entrypoint -t cmd-test:0.1 . # 運行鏡像 $ docker run entrypoint-test:0.1 . .. .dockerenv bin dev etc home lib lib64 lost+found ... # 我們的命令,是直接拼接在我們得ENTRYPOINT命令後面的 $ docker run entrypoint-test:0.1 -l total 56 drwxr-xr-x 1 root root 4096 May 16 06:32 . drwxr-xr-x 1 root root 4096 May 16 06:32 .. -rwxr-xr-x 1 root root 0 May 16 06:32 .dockerenv lrwxrwxrwx 1 root root 7 May 11 2019 bin -> usr/bin drwxr-xr-x 5 root root 340 May 16 06:32 dev drwxr-xr-x 1 root root 4096 May 16 06:32 etc drwxr-xr-x 2 root root 4096 May 11 2019 home lrwxrwxrwx 1 root root 7 May 11 2019 lib -> usr/lib lrwxrwxrwx 1 root root 9 May 11 2019 lib64 -> usr/lib64 ....
Dockerfile中很多命令都十分的相似,我們需要了解它們的區別,我們最好的學習就是對比他們然後測試效果!
實戰:Tomcat鏡像
1、準備鏡像文件
準備tomcat 和 jdk 到當前目錄,編寫好README
2、編寫dokerfile
$ vim dockerfile FROM centos # 基礎鏡像centos MAINTAINER cao<[email protected]> # 作者 COPY README /usr/local/README # 複製README文件 ADD jdk-8u231-linux-x64.tar.gz /usr/local/ # 添加jdk,ADD 命令會自動解壓 ADD apache-tomcat-9.0.35.tar.gz /usr/local/ # 添加tomcat,ADD 命令會自動解壓 RUN yum -y install vim # 安裝 vim 命令 ENV MYPATH /usr/local # 環境變量設置 工作目錄 WORKDIR $MYPATH ENV JAVA_HOME /usr/local/jdk1.8.0_231 # 環境變量: JAVA_HOME環境變量 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.35 # 環境變量: tomcat環境變量 ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.35 # 設置環境變量 分隔符是: ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin EXPOSE 8080 # 設置暴露的端口 CMD /usr/local/apache-tomcat-9.0.35/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.35/logs/catalina.out # 設置默認命令
3、構建鏡像
# 因爲dockerfile命名使用默認命名 因此不用使用-f 指定文件
$ docker build -t mytomcat:0.1 .
4、run鏡像
# -d:後臺運行 -p:暴露端口 --name:別名 -v:綁定路徑 $ docker run -d -p 8080:8080 --name tomcat01 -v /home/kuangshen/build/tomcat/test:/usr/local/apache-tomcat-9.0.35/webapps/test -v /home/kuangshen/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.35/logs mytomcat:0.1
5、訪問測試
$ docker exec -it 自定義容器的id /bin/bash
$ cul localhost:8080
6、發佈項目
(由於做了卷掛載,我們直接在本地編寫項目就可以發佈了!)
發現:項目部署成功,可以直接訪問!
我們以後開發的步驟:需要掌握Dockerfile的編寫!我們之後的一切都是使用docker鏡像來發布運行!
發佈自己的鏡像
發佈到 Docker Hub
1、地址 https://hub.docker.com/
2、確定這個賬號可以登錄
3、登錄
$ docker login --help Usage: docker login [OPTIONS] [SERVER] Log in to a Docker registry. If no server is specified, the default is defined by the daemon. Options: -p, --password string Password --password-stdin Take the password from stdin -u, --username string Username $ docker login -u 你的用戶名 -p 你的密碼
4、提交 push鏡像
# 會發現push不上去,因爲如果沒有前綴的話默認是push到 官方的library # 解決方法: # 第一種 build的時候添加你的dockerhub用戶名,然後在push就可以放到自己的倉庫了 $ docker build -t kuangshen/mytomcat:0.1 . # 第二種 使用docker tag #然後再次push $ docker tag 容器id kuangshen/mytomcat:1.0 #然後再次push $ docker push kuangshen/mytomcat:1.0
發佈到 阿里雲鏡像服務上
看官網 很詳細https://cr.console.aliyun.com/repository/
$ sudo docker login --username=zchengx registry.cn-shenzhen.aliyuncs.com $ sudo docker tag [ImageId] registry.cn-shenzhen.aliyuncs.com/dsadxzc/cheng:[鏡像版本號] # 修改id 和 版本 sudo docker tag a5ef1f32aaae registry.cn-shenzhen.aliyuncs.com/dsadxzc/cheng:1.0 # 修改版本 $ sudo docker push registry.cn-shenzhen.aliyuncs.com/dsadxzc/cheng:[鏡像版本號]
小結
Docker 網絡
理解Docker 0
學習之前清空下前面的docker 鏡像、容器
# 刪除全部容器 $ docker rm -f $(docker ps -aq) # 刪除全部鏡像 $ docker rmi -f $(docker images -aq)
測試
三個網絡
問題: docker 是如果處理容器網絡訪問的?
# 測試 運行一個tomcat $ docker run -d -P --name tomcat01 tomcat # 查看容器內部網絡地址 $ docker exec -it 容器id ip addr # 發現容器啓動的時候會得到一個 eth0@if91 ip地址,docker分配! $ ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 261: eth0@if91: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0 valid_lft forever preferred_lft forever # 思考? linux能不能ping通容器內部! 可以 容器內部可以ping通外界嗎? 可以! $ ping 172.18.0.2 PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data. 64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.069 ms 64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.074 ms
原理
1、我們每啓動一個docker容器,docker就會給docker容器分配一個ip,我們只要按照了docker,就會有一個docker0橋接模式,使用的技術是veth-pair技術!
https://www.cnblogs.com/bakari/p/10613710.html
再次測試 ip addr
2 、再啓動一個容器測試,發現又多了一對網絡
# 我們發現這個容器帶來網卡,都是一對對的 # veth-pair 就是一對的虛擬設備接口,他們都是成對出現的,一端連着協議,一端彼此相連 # 正因爲有這個特性 veth-pair 充當一個橋樑,連接各種虛擬網絡設備的 # OpenStac,Docker容器之間的連接,OVS的連接,都是使用evth-pair技術
3、我們來測試下tomcat01和tomcat02是否可以ping通
# 獲取tomcat01的ip 172.17.0.2 $ docker-tomcat docker exec -it tomcat01 ip addr 550: eth0@if551: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever # 讓tomcat02 ping tomcat01 $ docker-tomcat docker exec -it tomcat02 ping 172.17.0.2 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. 64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.098 ms 64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.071 ms # 結論:容器和容器之間是可以互相ping通
網絡模型圖
結論:tomcat01和tomcat02公用一個路由器,docker0。
所有的容器不指定網絡的情況下,都是docker0路由的,docker會給我們的容器分配一個默認的可用ip。
小結
Docker使用的是Linux的橋接,宿主機是一個Docker容器的網橋 docker0
Docker中所有網絡接口都是虛擬的,虛擬的轉發效率高(內網傳遞文件)
只要容器刪除,對應的網橋一對就沒了!
思考一個場景:我們編寫了一個微服務,database url=ip: 項目不重啓,數據ip換了,我們希望可以處理這個問題,可以通過名字來進行訪問容器?
–-link
$ docker exec -it tomcat02 ping tomca01 # ping不通 ping: tomca01: Name or service not known # 運行一個tomcat03 --link tomcat02 $ docker run -d -P --name tomcat03 --link tomcat02 tomcat 5f9331566980a9e92bc54681caaac14e9fc993f14ad13d98534026c08c0a9aef # 3連接2 # 用tomcat03 ping tomcat02 可以ping通 $ docker exec -it tomcat03 ping tomcat02 PING tomcat02 (172.17.0.3) 56(84) bytes of data. 64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.115 ms 64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.080 ms # 2連接3 # 用tomcat02 ping tomcat03 ping不通
探究:
docker network inspect 網絡id 網段相同
docker inspect tomcat03
查看tomcat03裏面的/etc/hosts發現有tomcat02的配置
–link 本質就是在hosts配置中添加映射
現在使用Docker已經不建議使用–link了!
自定義網絡,不適用docker0!
docker0問題:不支持容器名連接訪問!
自定義網絡
docker network connect -- Connect a container to a network create -- Creates a new network with a name specified by the disconnect -- Disconnects a container from a network inspect -- Displays detailed information on a network ls -- Lists all the networks created by the user prune -- Remove all unused networks rm -- Deletes one or more networks
查看所有的docker網絡
網絡模式
bridge :橋接 docker(默認,自己創建也是用bridge模式)
none :不配置網絡,一般不用
host :和所主機共享網絡
container :容器網絡連通(用得少!侷限很大)
測試
# 我們直接啓動的命令 --net bridge,而這個就是我們得docker0 # bridge就是docker0 $ docker run -d -P --name tomcat01 tomcat 等價於 => docker run -d -P --name tomcat01 --net bridge tomcat # docker0,特點:默認,域名不能訪問。 --link可以打通連接,但是很麻煩! # 我們可以 自定義一個網絡 $ docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
$ docker network inspect mynet;
啓動兩個tomcat,再次查看網絡情況
在自定義的網絡下,服務可以互相ping通,不用使用–link
我們自定義的網絡docker當我們維護好了對應的關係,推薦我們平時這樣使用網絡!
好處:
redis -不同的集羣使用不同的網絡,保證集羣是安全和健康的
mysql-不同的集羣使用不同的網絡,保證集羣是安全和健康的
網絡連通
# 測試兩個不同的網絡連通 再啓動兩個tomcat 使用默認網絡,即docker0
$ docker run -d -P --name tomcat01 tomcat
$ docker run -d -P --name tomcat02 tomcat
# 此時ping不通
# 要將tomcat01 連通 tomcat—net-01 ,連通就是將 tomcat01加到 mynet網絡
# 一個容器兩個ip(tomcat01)
# 01連通 ,加入後此時,已經可以tomcat01 和 tomcat-01-net ping通了
# 02是依舊不通的
結論:假設要跨網絡操作別人,就需要使用docker network connect 連通!
實戰:部署Redis集羣
# 創建網卡 docker network create redis --subnet 172.38.0.0/16 # 通過腳本創建六個redis配置 for port in $(seq 1 6);\ do \ mkdir -p /mydata/redis/node-${port}/conf touch /mydata/redis/node-${port}/conf/redis.conf cat << EOF >> /mydata/redis/node-${port}/conf/redis.conf port 6379 bind 0.0.0.0 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 cluster-announce-ip 172.38.0.1${port} cluster-announce-port 6379 cluster-announce-bus-port 16379 appendonly yes EOF done # 通過腳本運行六個redis for port in $(seq 1 6);\ docker run -p 637${port}:6379 -p 1667${port}:16379 --name redis-${port} \ -v /mydata/redis/node-${port}/data:/data \ -v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf docker exec -it redis-1 /bin/sh #redis默認沒有bash redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
docker搭建redis集羣完成!
我們使用docker之後,所有的技術都會慢慢變得簡單起來!
SpringBoot微服務打包Docker鏡像
1、構建SpringBoot項目
2、打包運行
mvn package
3、編寫dockerfile
FROM java:8 COPY *.jar /app.jar CMD ["--server.port=8080"] EXPOSE 8080 ENTRYPOINT ["java","-jar","app.jar"]
創建一個dockerfile文件,放入上面的代碼,把jar和文件上傳到xshell
4、構建鏡像
# 1.複製jar和DockerFIle到服務器 # 2.構建鏡像 $ docker build -t xxxxx:xx .
5、發佈運行
以後我們使用了Docker之後,給別人交付就是一個鏡像即可!