Docker是一個開源的應用容器引擎,使用Go語言開發,基於Linux內核的cgroup, namespace, Union FS等技術,對應用進程進行封裝隔離,而且獨立於宿主機與其餘進程,這種運行時封裝的狀態稱爲容器。Docker早起版本實現是基於LXC,並進一步對其封裝,包括文件系統、網絡互聯、鏡像管理等方面,極大簡化了容器管理。從0.7版本之後開始去除LXC,轉爲自行研發的libcontainer,從1.11版本開始,進一步演進爲使用runC和containerd。
Docker理念是將應用及依賴包打包到一個可移植的容器中,可發佈到任意Linux發行版Docker引擎上。使用沙箱機制運行程序,程序之間相互隔離。html
Containerd:是一個簡單的守護進程,使用runC管理容器。向Docker Engine提供接口。
Shim:只負責管理一個容器。
runC:是一個輕量級的工具, 只用來運行容器。java
Namespaces
命名空間, Linux內核提供的一種對進程資源隔離的機制,例如進程、網絡、掛載點等資源。
CGroupsnode
控制組, Linux內核提供的一種限制進程資源的機制; 例如CPU、內存等資源。
UnionFS
聯合文件系統,支持將不一樣位置的目錄掛載到同一虛擬文件系統, 造成一種分層的模型。mysql
虛擬機與容器的區別linux
以KVM舉例,與Docker對比nginx
啓動時間
Docker秒級啓動, KVM分鐘級啓動。git
輕量級
容器鏡像大小一般以M爲單位,虛擬機以G爲單位。
容器資源佔用小,要比虛擬機部署更快速。github
性能
容器共享宿主機內核,系統級虛擬化,佔用資源少,沒有Hypervisor層開銷,容器性能基本接近物理機;
虛擬機須要Hypervisor層支持,虛擬化一些設備,具備完整的GuestOS,虛擬化開銷大,於是下降性能,沒有容器性能好。web
安全性
因爲共享宿主機內核,只是進程級隔離,所以隔離性和穩定性不如虛擬機,容器具備必定權限訪問宿主機內核,存在必定安全隱患。redis
使用要求
KVM基於硬件的徹底虛擬化,須要硬件CPU虛擬化技術支持;
容器共享宿主機內核,可運行在主流的Linux發行版,不用考慮CPU是否支持虛擬化技術。
應用場景
場景一: 節省項目環境部署時間
1. 單項目打包
2. 整套項目打包
3. 新開源技術試用
場景二: 環境一致性
場景三: 持續集成
場景四: 微服務
場景五: 彈性伸縮
Linux 環境下docker的安裝
基於centos7的環境下
# 安裝依賴包
yum install -y yum-utils device-mapper-persistent-data lvm2
# 添加軟件源信息 源地址換成阿里
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 更新yum包索引
yum makecache fast
# 安裝Docker CE
yum install docker-ce
# 啓動
systemctl start docker
# 卸載
yum remove docker-ce
rm -rf /var/lib/docker
#卸載centos自帶的firewall
systemctl stop firewalld.service #關閉防火牆
systemctl disable firewalld.service #關閉開機啓動
#下載iptables
yum install iptables (根據centOS7的版本和內核,有些版本已經裝過,能夠跳過此命令)
yum install iptables-services
service iptables restart
chkconfig iptables on或者
systemctl enable iptables.service #開機自啓
鏡像與配置國內鏡像倉庫
簡單說, Docker鏡像是一個不包含Linux內核而又精簡的Linux操做系統
Docker Hub是由Docker公司負責維護的公共註冊中心,包含大量的容器鏡像, Docker工具
默認從這個公共鏡像庫下載鏡像
https://hub.docker.com/explore
默認是國外的源,下載會慢,建議配置國內鏡像倉庫:
# vim /etc/docker/daemon.json
{
"registry-mirrors": [ "https://registry.docker-cn.com"]
}
鏡像與容器的關係
鏡像不是一個單一的文件,而是有多層構成。 咱們能夠經過docker history <ID/NAME> 查看鏡像中各層內容及大小,每層對應着Dockerfile中的一條指令。 Docker鏡像默認存儲在/var/lib/docker/<storage-driver>中。
容器實際上是在鏡像的最上面加了一層讀寫層,在運行容器裏作的任何文件改動, 都會寫到這個讀寫層。 若是容器刪除了,最上面的讀寫層也就刪除了,改動也就丟失了。Docker使用存儲驅動管理鏡像每層內容及可讀寫層的容器層。
容器管理指令
指令 |
描述 |
ls |
列出鏡像 |
build |
建立 |
inspect |
顯示一個或多個鏡像詳細信息 |
pull |
從鏡像倉庫拉取鏡像 |
push |
推送一個鏡像到鏡像倉庫 |
rm |
移除一個或多個鏡像 |
prune |
移除未使用的鏡像,沒有被標記或被任何容器引用的 |
tag |
建立一個引用源鏡像標記目標鏡像 |
export |
導出容器文件系統到tar歸檔文件 |
import |
導入容器文件系統tar歸檔溫江建立鏡像 |
save |
保存一個或多個鏡像到一個tar歸檔文件 |
load |
加載鏡像來自tar歸檔或標準輸入 |
#docker 導出一個鏡像
docker save nginx:1.11 > nginx1.11.tar
#docker 導入一個鏡像
docker load < nginx1.11.tar
#docker 導出一個容器
docker export 82df6c127b53 > nginx_start.tar
#docker 導入一個容器
docker import nginx_start.tar
#命名一個名字 和標記
docker import nginx_start.tar nginx:self
#建立容器,並命名
docker run -itd --name web_1 nginx:1.11
#這個容器打開一個新的窗口
docker container exec -it web_1 bash
#帶一個變量到容器中
docker container run -itd -e a=123 --name web_2 nginx:1.11
#內存&cpu使用率
docker container stats web_2
指令 |
描述 |
-t, --interactive |
交互式 |
-t, --tty |
分配一個僞終端 |
-a, --attach list |
附加到運行的容器 |
--dns list |
設置dns服務器 |
-e --env list |
設置環境變量 |
--env-file list |
從文件讀取環境變量 |
-p, --publish list |
發佈容器端口到宿主機 |
-P, --publish-all |
發佈容器的全部EXPOSE的端口到宿主機隨機端口 |
-h, --hostname string |
設置容器主機名 |
--ip string |
指定容器ip, 只能用於自定義網絡 |
--link string |
添加鏈接到另外一個容器 |
--network |
鏈接容器到一個網絡 |
--mount month |
掛載宿主機分區到容器 |
-v, --volume list |
掛載宿主機目錄到容器 |
--restart string |
容器退出時重啓策略,默認no[always|on-failure] |
--add-host list |
添加其餘主機到容器中 /etc/hosts |
資源限制指令 |
描述 |
-m, --memory |
容器能夠使用的最大內存量 |
--memory-swap |
容許交換到磁盤的內存量 |
--cpus |
限制容器能夠使用多少可用的cpu資源 |
--cpuset-cpus |
限制容器能夠使用的特定的cpu |
容器管理經常使用命令
指令 |
描述 |
ls |
列出容器 |
inspect |
顯示一個或多個容器詳細信息 |
attach |
附加本地標準輸入,輸出和錯誤到一個運行的容器 |
exec |
再運行容器中執行命令 |
commit |
建立一個新鏡像來自一個容器 |
cp |
拷貝文件/文件夾到一個容器 |
logs |
獲取一個容器日誌 |
port |
列出一個容器日誌 |
stats |
顯示容器資源使用統計 |
top |
顯示一個容器運行的進程 |
update |
更新一個或多個容器 |
stop/start |
中止/啓動一個或多個容器 |
rm |
刪除一個或多個容器 |
4. 管理應用程序數據
將docker主機書籍掛載到容器
Docker提供三種不一樣的方式將數據從宿主機掛載到容器中:volumes, bind mounts 和tmpfs
volumes: docker管理宿主機文件系統的一部分(/var/lib/docker/volumes)
bind mounts: 能夠存儲在宿主機系統的任意位置
tmpfs:掛載存儲在宿主機系統的內存中,而不會寫入宿主機的文件系統
Volume
管理卷:
# docker volume create nginx-vol
# docker volume ls
# docker volume inspect nginx-vol
用卷建立一個容器:
# docker run -d -it --name=nginx-test --mount src=nginx-vol,dst=/usr/share/nginx/html nginx
# docker run -d -it --name=nginx-test -v nginx-vol:/usr/share/nginx/html nginx
清理:
# docker container stop nginx-test
# docker container rm nginx-test
# docker volume rm nginx-vol
注意:
1. 若是沒有指定卷,自動建立。
2. 建議使用—mount,更通用
Bind Mounts
用卷建立一個容器:
#docker run -d -it --name=nginx-test --mount type=bind,src=/app/wwwroot,dst=/usr/share/nginx/html nginx
# docker run -d -it --name=nginx-test -v /app/wwwroot:/usr/share/nginx/html nginx
驗證綁定:
# docker inspect nginx-test
清理:
# docker container stop nginx-test
# docker container rm nginx-test
注意:
1. 若是源文件/目錄沒有存在,不會自動建立,會拋出一個錯誤。
2. 若是掛載目標在容器中非空目錄,則該目錄現有內容將被隱藏。
Dockerfile指令
指令 |
描述 |
指令 |
描述 |
FROM |
構建的鏡像是基於哪一個鏡像的。例如:FROM:centos:6 |
COPY |
拷貝文件或目錄到鏡像,用法同上 例如: COPY ./start.sh /start.sh |
MAINTAINER |
鏡像的維護者 |
ENTRYPOINT |
運行容器時執行的Shell命令 例如: ENTRYPOINT [「/bin/bash", 「-c", 「/start.sh"] ENTRYPOINT /bin/bash -c ‘/start.sh |
RUN |
構建鏡像時運行的shell命令 例如: RUN[「yum」,」install」,」httpd」] RUN yum install httpd |
VOLUME |
指定容器掛載點到宿主機自動生成的目錄或其餘容器 例如: VOLUME ["/var/lib/mysql"] |
CMD |
運行容器時執行的shell命令 例如: CMD[「-c」,」/start.sh」] CMD[「/usr/sbin/sshd」,」-D」] CMD /usr/sbin/sshd -D |
USER |
爲RUN、 CMD和ENTRYPOINT執行命令指定運行用戶 USER <user>[:<group>] or USER <UID>[:<GID>] 例如: USER augustyang |
EXPOSE |
聲明容器運行的服務端口 例如:EXPOSE 90 3306 |
WORKDIR |
爲RUN CMD ENTRYPOINT COPY 設置工做目錄 |
ENV |
設置環境變量 例如 ENV JAVA_HOME /kitty/jdk1.7.0_80 |
HEALTHCHECK |
健康檢查
|
ADD |
拷貝文件或目錄到鏡像,若是是URL或壓縮包會自動下載或自動解壓 ADD <src>… <dest> ADD [「<src>」,… 「<dest>」] ADD https://xxx.com/html.tar.gz /var/www/html ADD html.tar.gz /var/www/html |
ARG |
在構建鏡像時指定一些參數 例如 FROM centos:6 ARG user #ARG user=root USER $user #docker build --build-arg user=augustyang Dockerfile . |
build 構建
docker build -t nginx:v3 .
CMD與ENTRYPOINT的區別
FROM centos:6
MAINTAINER yang_yang
RUN mkdir /ysl
RUN touch /ysl/test.txt
ENTRYPOINT ["echo","ENTRYPOINT"]
CMD ["CMD"]
注:ENTRYPOINT須要放在CDM前面 。
docker run image_name 輸出:ENTRYPOINT CMD
docker run image_name ysl 輸出:ENTRYPOINT ysl
1)啓動容器沒帶參數:起默認參數,
2)啓動容器帶參數:所帶參數替換默認參數
構建java的dockerfile
FROM centos:6
MAINTAINER yang_yang
ENV JAVA_HOME /kitty/jdk1.7.0_80
ADD apache-tomcat-8.0.43.tar.gz /kitty
WORKDIR /kitty/apache-tomcat-8.0.43
EXPOSE 8080
ENTRYPOINT ["./bin/catalina.sh", "run"]
啓動一個tomcat的示例
docker run -d -it \
-p 8084:8080 \
--name=kitty_notice \
--link mysql:db \
--net kitty \
--ip 172.18.0.8 \
-v /kitty/jdk1.7.0_80:/kitty/jdk1.7.0_80 \
-v/data:/data \
--mount type=bind,src=/kitty/kitty_notice,dst=/kitty/apache-tomcat-8.0.43/webapps \
tomcat:v1
#安裝必要的一些系統工具
yum install -y yum-utils device-mapper-persistent-data lvm2
#添加軟件源信息 源地址換成阿里
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#更新並安裝 Docker-CE
yum makecache fast
yum -y install docker-ce
https://github.com/vmware/harbor/releases #下載離線包(二進制)
安裝docker-compose
下載docker-compose
unzip docker-compose-linux-x86_64.zip
mv docker-compose /usr/bin
chmox +x /usr/bin/docker-compose
自籤TLS證書
https://github.com/vmware/harbor/blob/master/docs/configure_https.md
1) 進入harbor裏面, 建立ssl 目錄 # mkdir harbor/ssl && cd harbor/ssl
2) #Create your own CA certificate
openssl req -newkey rsa:4096 -nodes -sha256 -keyout ca.key -x509 -days 365 -out ca.crt
3) 生成證書籤名
openssl req -newkey rsa:4096 -nodes -sha256 -keyout reg.yangshanlei.com.key -out reg.yangshanlei.com.csr
4) 生成註冊表主機的證書
openssl x509 -req -days 365 -in reg.yangshanlei.com.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out reg.yangshanlei.com.crt
Harbor安裝與配置
1)修改配置文件 vim harbor.cfg
hostname = reg.yangshanlei.com
ui_url_protocol = https
ssl_cert = ./ssl/reg.yangshanlei.com.crt
ssl_cert_key = ./ssl/reg.yangshanlei.com.key
harbor_admin_password = 12345
2) ./prepare
3) ./install.sh
4) docker-compose ps
Docker主機訪問Harbor
客戶端
hosts配置文件修改 192.168.2.84 reg.yangshanlei.com
mkdir -p /etc/docker/certs.d/reg.yangshanlei.com/
scp root@192.168.2.84:/root/harbor/ssl/reg.yangshanlei.com.crt /etc/docker/certs.d/reg.yangshanlei.com/
docker login reg.yangshanlei.com -u test -p Yangshanlei@2018 #私有倉庫須要登陸才能下載和上傳, 公開倉庫沒有上傳的權限
Portainer
Portainer是一個開源、輕量級Docker管理用戶界面,基於Docker API,可管理Docker主機或Swarm集羣,支持最新版Docker和Swarm模式
一、建立卷
# docker volume create portainer_data
二、建立Portainer容器
# docker run -d \
-p 9000:9000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer
cAdvisor+InfluxDB+Grafana
Influxdb #數據庫
docker run -d \
--name influxdb \
--net monitor \
-p 7083:8083 \
-p 7086:8086 \
tutum/influxdb
cAdvisor
docker run -d \
--name=cadvisor \
--net monitor \
-p 7081:8080 \
--mount type=bind,src=/,dst=/rootfs,ro \
--mount type=bind,src=/var/run,dst=/var/run \
--mount type=bind,src=/sys,dst=/sys,ro \
--mount type=bind,src=/var/lib/docker/,dst=/var/lib/docker,ro \
google/cadvisor \
-storage_driver=influxdb \
-storage_driver_db=cadvisor \
-storage_driver_host=influxdb:8086
Grafana
docker run -d \
--name grafana \
--net monitor \
-p 3000:3000 \
grafana/grafana
mongdb docker-compose
version: '3' services: mongo: image: mongo:3.4 restart: always ports: - 27017:27017 - 28017:28017 environment: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: 123456 TZ: Asia/Shanghai volumes: - /data/db:/data/db
項目軟件和程序放在一塊兒(一個遊戲項目)
tomcat Dockerfile +apache-tomcat-8.0.43.tar.gz
FROM centos:6 MAINTAINER yang_yang ENV JAVA_HOME /kitty/jdk1.7.0_80 ADD apache-tomcat-8.0.43.tar.gz /kitty RUN sed -i '1a JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom"' /kitty/apache-tomcat-8.0.43/bin/catalina.sh\ && /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone WORKDIR /kitty/apache-tomcat-8.0.43 EXPOSE 8080 ENTRYPOINT ["./bin/catalina.sh", "run"]
redis Dockerfile + redis-3.2.5.tar.gz
FROM centos:6 ADD redis-3.2.5.tar.gz /opt/ RUN yum -y install gcc net-tools make zip unzip RUN cd /opt/redis-3.2.5/src/ && make && make install\ && cd /opt/redis-3.2.5/utils/ && echo | /bin/bash install_server.sh\ && sed -i 's/bind 127.0.0.1/bind 0.0.0.0/g' /etc/redis/6379.conf\ && sed -i 's/# requirepass foobared/requirepass 123456/g' /etc/redis/6379.conf\ && /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone EXPOSE 6379 ENTRYPOINT /usr/local/bin/redis-server /etc/redis/6379.conf && tail -f -n20 /var/log/redis_6379.log
mysql 建立2個目錄:conf (存放my.cnf) data (數據持久化)
[mysqld] user=mysql port=3306 datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock pid-file=/var/run/mysql/mysql.pid log_error=/var/log/mysql/error.log character_set_server = utf8 max_connections=3600
game Dockerfile
FROM centos:6 MAINTAINER yang_yang ENV JAVA_HOME /kitty/jdk1.7.0_80 RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone EXPOSE 3301 EXPOSE 23301 EXPOSE 1234 WORKDIR /kitty/kitty_game/bin ENTRYPOINT bash /kitty/kitty_game/bin/game.sh start && tail -f /dev/null
friend Dockerfile
FROM centos:6 MAINTAINER yang_yang ENV JAVA_HOME /kitty/jdk1.7.0_80 RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone EXPOSE 43301 WORKDIR /kitty/kitty_friend/bin ENTRYPOINT bash /kitty/kitty_friend/bin/game.sh start && tail -f /dev/null
docker-compose
version: '3' services: zk1: image: zookeeper restart: always hostname: zk1 ports: - 2181:2181 networks: - kitty environment: ZOO_MY_ID: 1 ZOO_SERVERS: server.1=0.0.0.0:2888:3888 server.2=zk2:2888:3888 server.3=zk3:2888:3888 TZ: Asia/Shanghai zk2: image: zookeeper restart: always hostname: zk2 ports: - 2182:2181 networks: - kitty environment: ZOO_MY_ID: 2 ZOO_SERVERS: server.1=zk1:2888:3888 server.2=0.0.0.0:2888:3888 server.3=zk3:2888:3888 TZ: Asia/Shanghai zk3: image: zookeeper restart: always hostname: zk3 ports: - 2183:2181 networks: - kitty environment: ZOO_MY_ID: 3 ZOO_SERVERS: server.1=zk1:2888:3888 server.2=zk3:2888:3888 server.3=0.0.0.0:2888:3888 TZ: Asia/Shanghai kafka1: image: wurstmeister/kafka hostname: kafka1 restart: always ports: - 9092:9092 networks: - kitty environment: KAFKA_BROKER_ID: 1 KAFKA_ZOOKEEPER_CONNECT: zk2:2181,zk1:2181,zk3:2181 KAFKA_ADVERTISED_HOST_NAME: kafka1 KAFKA_ADVERTISED_PORT: 9092 TZ: Asia/Shanghai kafka2: image: wurstmeister/kafka hostname: kafka2 restart: always ports: - 9093:9092 networks: - kitty environment: KAFKA_BROKER_ID: 2 KAFKA_ZOOKEEPER_CONNECT: zk2:2181,zk1:2181,zk3:2181 KAFKA_ADVERTISED_HOST_NAME: kafka2 KAFKA_ADVERTISED_PORT: 9092 TZ: Asia/Shanghai kafka3: image: wurstmeister/kafka hostname: kafka3 restart: always ports: - 9094:9092 networks: - kitty environment: KAFKA_BROKER_ID: 3 KAFKA_ZOOKEEPER_CONNECT: zk2:2181,zk1:2181,zk3:2181 KAFKA_ADVERTISED_HOST_NAME: kafka3 KAFKA_ADVERTISED_PORT: 9092 TZ: Asia/Shanghai kitty_mysql: hostname: kitty_mysql image: mysql:5.6 ports: - 3306:3306 networks: - kitty volumes: - ./mysql/conf:/etc/mysql/conf.d - ./mysql/data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: 123456 MYSQL_USER: kitty MYSQL_PASSWORD: kitty TZ: Asia/Shanghai kitty_redis: hostname: kitty_redis build: context: ./redis dockerfile: Dockerfile ports: - 6379:6379 networks: - kitty kitty_auth: hostname: kitty_auth build: context: ./tomcat dockerfile: Dockerfile ports: - 8081:8080 networks: - kitty volumes: - /kitty/kitty_auth:/kitty/apache-tomcat-8.0.43/webapps - /kitty/jdk1.7.0_80:/kitty/jdk1.7.0_80 - /data:/data kitty_activity: hostname: kitty_activity build: context: ./tomcat dockerfile: Dockerfile ports: - 8082:8080 networks: - kitty volumes: - /kitty/kitty_activity:/kitty/apache-tomcat-8.0.43/webapps - /kitty/jdk1.7.0_80:/kitty/jdk1.7.0_80 - /data:/data kitty_gm: hostname: kitty_gm build: context: ./tomcat dockerfile: Dockerfile ports: - 8083:8080 networks: - kitty volumes: - /kitty/kitty_gm:/kitty/apache-tomcat-8.0.43/webapps - /kitty/jdk1.7.0_80:/kitty/jdk1.7.0_80 - /data:/data kitty_idip: hostname: kitty_idip build: context: ./tomcat dockerfile: Dockerfile ports: - 8084:8080 networks: - kitty volumes: - /kitty/kitty_idip:/kitty/apache-tomcat-8.0.43/webapps - /kitty/jdk1.7.0_80:/kitty/jdk1.7.0_80 - /data:/data kitty_notice: hostname: kitty_notice build: context: ./tomcat dockerfile: Dockerfile ports: - 8085:8080 networks: - kitty volumes: - /kitty/kitty_notice:/kitty/apache-tomcat-8.0.43/webapps - /kitty/jdk1.7.0_80:/kitty/jdk1.7.0_80 - /data:/data kitty_game: hostname: kitty_game restart: always build: ./game ports: - 3301:3301 networks: - kitty volumes: - /kitty/jdk1.7.0_80:/kitty/jdk1.7.0_80 - /kitty/kitty_game:/kitty/kitty_game - /data:/data kitty_friend: hostname: kitty_friend restart: always build: ./friend ports: - 43301:43301 networks: - kitty volumes: - /kitty/jdk1.7.0_80:/kitty/jdk1.7.0_80 - /kitty/kitty_friend:/kitty/kitty_friend - /data:/data networks: kitty:
ps: 全部的軟件和程序都放在一塊兒, 每次啓停都把依賴的軟件都重啓了,不推薦
程序和軟件分離 建立2個docker-compose: 須要注意的的是每一個軟件不須要指定網絡例如.只在最後指定下網絡,這樣2個docker-compose 就能夠網絡互連, kitty這個網絡須要事先先建立