原文: Docker初探
前言
學(xué)習(xí)環(huán)境是本地虛擬機(jī), linux版本使用CentOS 7.
由于使用最小安裝方式, 在學(xué)習(xí)Docker之前, 順帶總結(jié)了下jdk安裝和防火墻相關(guān)配置.
一: jdk安裝
在Centos下安裝jdk有多種方式, 例如手動(dòng)下載tar文件解壓, yum安裝, rpm安裝等.
這里我用yum方式安裝:
-
yum list installed |grep java
查看系統(tǒng)中是否已經(jīng)安裝jdk, 如果有安裝想卸載:
yum remove xxx
即可.
-
yum list java-1.8.0*
或yum search java|grep jdk
查看yum庫(kù)中的jdk安裝包.
-
yum -y install java-1.8.0-openjdk
這里我安裝jdk1.8
-
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.141-1.b16.el7_3.x86_64
安裝完成后的默認(rèn)目錄
驗(yàn)證java命令就可以了.
注意: 這種yum方式安裝的是openjdk, 并不是sun jdk. 如果想要sunjdk就用安裝方式.
因?yàn)檫@種方式使用alternatives進(jìn)行版本控制, 所以在沒(méi)有設(shè)置環(huán)境變量的情況下也可以執(zhí)行java命令.
但是對(duì)于tomcat或其他軟件要使用jdk的話就要設(shè)置環(huán)境變量了.
對(duì)于環(huán)境變量設(shè)置: 修改/etc/profile
文件
#set java environment
JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.141-1.b16.el7_3.x86_64
JRE_HOME=$JAVA_HOME/jre
CLASS_PATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
export JAVA_HOME JRE_HOME CLASS_PATH PATH
讓修改生效source /etc/profile
二: 防火墻配置
CentOS 7中默認(rèn)使用firewall作為防火墻, 而6.x中是iptables.
CentOS 7下防火墻的配置, 也支持iptables防火墻. 前提是需要關(guān)閉禁止firewall然后安裝iptables-services.
二者不能共用.
CentOS7下Firewall防火墻配置用法詳解(推薦): https://yq.aliyun.com/ziliao/94786
我覺(jué)得既然CentOS 7 中升級(jí)到了firewall防火墻, 就沒(méi)必要切換iptables. 不如就用firewall.
關(guān)于firewall的配置, 首先來(lái)看兩個(gè)目錄:
-
系統(tǒng)配置目錄:
/usr/lib/firewalld/services
目錄中存放定義好的網(wǎng)絡(luò)服務(wù)和端口參數(shù)揭保,系統(tǒng)參數(shù),不能修改
用戶(hù)配置目錄:
/etc/firewalld/
自定義添加端口
firewall支持兩種自定義添加的方式: 命令添加和配置文件添加.
其中, 命令添加方式也會(huì)在配置文件中體現(xiàn)
-
命令添加方式:
firewall-cmd --permanent --add-port=8050/tcp # 指定zone: firewall中有Zone的概念, 可以將具體的端口指定到具體的zone配置文件中. firewall-cmd --zone=public --permanent --add-port=8050/tcp
# 參數(shù)介紹: 1. firwall-cmd:是Linux提供的操作firewall的一個(gè)工具; 2. --permanent:表示設(shè)置為持久; 3. --add-port:標(biāo)識(shí)添加的端口; 4. --zone=public:指定的zone為public;
如果命令指定
–zone=dmz
, 會(huì)在dmz.xml文件中新增一條. 默認(rèn)zone=public
-
配置文件添加方式:
/etc/firewalld/zones
目錄下添加xml配置, 如public.xml:<?xml version="1.0" encoding="utf-8"?> <zone> <short>Public</short> <description>xxx</description> <service name="dhcpv6-client"/> <service name="ssh"/> <port protocol="tcp" port="8050"/> <port protocol="tcp" port="8761"/> </zone>
常用命令
firewall
# 查看firewall服務(wù)狀態(tài):
systemctl status firewalld
# 查看firewall的運(yùn)行狀態(tài)(running or not running):
firewall-cmd --state
# 查看防火墻規(guī)則:
firewall-cmd --list-all
# 查看已開(kāi)放的端口(--zone可以不寫(xiě), 默認(rèn)為public)
firewall-cmd --zone=public --list-ports
# 重啟, 開(kāi)啟, 關(guān)閉
service firewalld restart
service firewalld start
service firewalld stop
# or
systemctl [stop/stop/restart] firewalld
補(bǔ)充下iptables的基本使用吧
# 查看防火墻啟動(dòng)狀態(tài)
service iptables status
# 關(guān)閉防火墻
service iptables stop
# 啟動(dòng)防火墻
service iptables start
# 查看規(guī)則列表
iptables --list-rules
# 編輯規(guī)則
vim /etc/sysconfig/iptables
# 加入一行
-A INPUT -p tcp -m state --state NEW -m tcp --dport 25 -j ACCEPT
# 保存畜晰,重啟防火墻
service iptables restart
三: docker
安裝方式一
# docker安裝:
yum install -y docker-io
這里docker也可以, 網(wǎng)上有說(shuō)centos7以上用docker, 我這里用docker-io也沒(méi)問(wèn)題
# 啟動(dòng)
systemctl start docker
# 設(shè)置開(kāi)機(jī)啟動(dòng)
systemctl enable docker
# 查看docker信息
docker info
# 查看版本信息
docker version
安裝方式二
上面介紹了一鍵的安裝方式, 這里推薦使用官方的安裝方式
官方文檔: https://docs.docker.com/install/linux/docker-ce/centos/
卸載
$ sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine
$ sudo rm -rf /var/lib/docker
安裝
-
安裝相關(guān)工具類(lèi)
$ sudo yum install -y yum-utils \ device-mapper-persistent-data \ lvm2
-
配置docker倉(cāng)庫(kù)
$ sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
-
安裝docker
$ sudo yum install docker-ce
在第二步配置docker倉(cāng)庫(kù)
錯(cuò)誤:
Loaded plugins: fastestmirror
adding repo from: https://download.docker.com/linux/centos/docker-ce.repo
grabbing file https://download.docker.com/linux/centos/docker-ce.repo to /etc/yum.repos.d/docker-ce.repo
Could not fetch/save url https://download.docker.com/linux/centos/docker-ce.repo to file /etc/yum.repos.d/docker-ce.repo
: [Errno 14] curl#35 - "TCP connection reset by pe
這是由于國(guó)內(nèi)訪問(wèn)不到docker官方鏡像的緣故, 可以通過(guò)aliyun的源來(lái)完成
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
鏡像
在線拉取: http://hub.docker.com 中查找需要的鏡像
或docker search xxx
命令查找docker.io上的鏡像
- 例如Mysql鏡像: 使用
docker pull mysql
, 會(huì)默認(rèn)從docker.io中拉取.
Tip: docker.io太慢可以用國(guó)內(nèi)的鏡像倉(cāng)庫(kù)
hub.daocloud.io
, 或使用daocloud加速器
離線安裝: 拷貝tar包至文件中: docker load <./xxx.tar
列出當(dāng)前鏡像: docker images
打包鏡像: docker save >./mysql123.tar docker
容器
docker create
: image(unioned read file system) -> container(unioned RW file system)
容器創(chuàng)建. 在鏡像創(chuàng)建一個(gè)容器后加了一層讀寫(xiě)層
docker start
: 在容器(container)之上啟動(dòng)一個(gè)可使用的進(jìn)程空間, 執(zhí)行后會(huì)進(jìn)入Created狀態(tài)
docker create -p 3308:3306 --name mysql2 -e MYSQL_ROOT_PASSWORD=root docker.io/mysql:5.7.14
docker start [container id]
docker run
來(lái)啟動(dòng)容器
該命令實(shí)際包含兩個(gè)命令: docker create
和docker start
# 例如啟動(dòng)兩個(gè)mysql
docker run -d -p 3306:3306 --name mysql1 -e MYSQL_ROOT_PASSWORD=root docker.io/mysql:5.7.14
docker run -d -p 3308:3306 --name mysql2 -e MYSQL_ROOT_PASSWORD=root docker.io/mysql:5.7.14
參數(shù)解釋:
-d: 后臺(tái)運(yùn)行
-p: 對(duì)外暴露的端口
-e: 環(huán)境參數(shù)
--name: 指定容器名(不指定的話系統(tǒng)隨機(jī)分配name名)
# 查看容器(加-a表示包括運(yùn)行和非運(yùn)行所有狀態(tài)的)
docker ps -a
# 停止
docker stop [id]
# 刪除容器(-f:強(qiáng)制)
docker rm -f [id]
# 刪除鏡像
docker rmi [imageID]
注意: 容器在運(yùn)行狀態(tài)時(shí): 可以強(qiáng)制刪除容器, 但不能強(qiáng)制刪除鏡像.
進(jìn)入容器: docker exec -it [container name or conteiner id] /bin/bash
數(shù)據(jù)卷
容器中管理數(shù)據(jù)主要有兩種方式:
數(shù)據(jù)卷(Data Volumes)
數(shù)據(jù)卷容器(Data Volumes Dontainers)
數(shù)據(jù)卷管理示例
docker run -d -it --name=centos1 -v /root/dbdata:/test/dbdata docker.io/centos:7.2.1511
# 參數(shù)解釋
-v: 掛載一個(gè)本地的目錄到容器中作為數(shù)據(jù)卷.
例如: -v /xx:/yy: 將容器中的目錄/yy掛載到機(jī)器中/xx中
這里我遇到過(guò)一個(gè)問(wèn)題:
Permission denied
這可能會(huì)導(dǎo)致容器中映射的目錄無(wú)權(quán)限打開(kāi), 或者啟動(dòng)容器后是exited狀態(tài).
可以通過(guò)
docker logs [container id]
查看日志.原因是SELinux導(dǎo)致的. 這貨的訪問(wèn)控制策略相當(dāng)復(fù)雜, 很多運(yùn)維人員的建議都是將他關(guān)閉.
查看SELinux狀態(tài):/usr/sbin/sestatus
或getenforce
關(guān)閉:vi /etc/selinux/config
文件, 將SELINUX=enforcing
值改為 disabled, 需要重啟.
- 在啟動(dòng)centos1容器后, 在宿主機(jī)
/root/dbdata
和容器/test/dbdata
中的任何操作都會(huì)互相映射, 相當(dāng)于一份數(shù)據(jù)的備份. - 關(guān)閉或者刪除centos1容器后, 宿主機(jī)數(shù)據(jù)依然在, 也可以啟動(dòng)多個(gè)容器, 映射數(shù)據(jù)卷目錄中的數(shù)據(jù).
示例: mysql數(shù)據(jù)備份
docker run -d -p 3307:3306 \
-v /mysql/data:/var/lib/mysql \
-v /mysql/config:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=root \
--name mysqldb1 \
docker.io/mysql:5.7.14
這里如果再啟一個(gè)mysqldb2測(cè)試, mysqldb1狀態(tài)是run, 啟動(dòng)mysqldb2后, 會(huì)出現(xiàn)mysqldb2異常關(guān)閉或連接不通的現(xiàn)象.
所以再啟動(dòng)mysqldb2容器時(shí)候, mysqldb1不能是run的狀態(tài), 因?yàn)樵?v參數(shù)中都有對(duì)
/mysql/data
目錄的讀寫(xiě)操作.
數(shù)據(jù)卷容器
數(shù)據(jù)卷容器: 其實(shí)就是一個(gè)正常容器, 專(zhuān)門(mén)用來(lái)提供數(shù)據(jù)卷供其他容器掛載.
如果你有持續(xù)更新的數(shù)據(jù)需要在容器之間共享. 那么可以創(chuàng)建數(shù)據(jù)卷容器.
-
創(chuàng)建創(chuàng)建一個(gè)數(shù)據(jù)卷容器 data_container
docker run -it -d -v /dbdata --name data_container docker.io/centos:7.2.1511
-
創(chuàng)建centos1, centos2 兩個(gè)容器, 并掛載data_container容器中的數(shù)據(jù)卷.
docker run -it -d --volumes-from data_container --name centos1 docker.io/centos:7.2.1511 docker run -it -d --volumes-from data_container --name centos2 docker.io/centos:7.2.1511
然后這兩個(gè)容器中都能夠共享到數(shù)據(jù)卷目錄/dbdata
和其中的數(shù)據(jù)了.
關(guān)于-v
參數(shù):
-
在創(chuàng)建數(shù)據(jù)卷容器時(shí),
-v /dbdata 或 -v /root/dbdata:/dbdata
都可以.前者只在數(shù)據(jù)卷容器中創(chuàng)建dbdata目錄, 不和本地宿主機(jī)映射.
后者會(huì)在本地宿主機(jī)也有映射的目錄
/root/dbdata
.
關(guān)于--volumes-from
參數(shù):
所掛載數(shù)據(jù)卷的容器自己并不需要保持在運(yùn)行狀態(tài).
可以使用多個(gè), 從而實(shí)現(xiàn)從多個(gè)容器中掛載多個(gè)數(shù)據(jù)卷.
可以從其他已經(jīng)掛載了數(shù)據(jù)卷的容器來(lái)掛載數(shù)據(jù)卷.
利用數(shù)據(jù)卷容器進(jìn)行數(shù)據(jù)遷移備份
- 備份
# 將數(shù)據(jù)卷容器(data_container)中的數(shù)據(jù)備份到宿主機(jī)的當(dāng)前目錄
docker run --volumes-from data_container -v $(pwd):/backup --name worker docker.io/centos:7.2.1511 tar cvf /backup/backup.tar /dbdata
這條命令包含以下幾個(gè)步驟:
首先利用centos鏡像創(chuàng)建了一個(gè)容器worker.
使用
--volumes-from
來(lái)讓worker容器掛載data_container容器的數(shù)據(jù)卷(即dbdata數(shù)據(jù)卷).使用-v $(pwd):/backup參數(shù)來(lái)掛載本地的當(dāng)前目錄到worker容器的/backup目錄.
-
worker容器啟動(dòng)后, 使用了
tar cvf /backup/backup.tar /dbdata
命令來(lái)將/dbdata
下內(nèi)容備份為容器內(nèi)的/backup/backup.tar, 即也映射到宿主主機(jī)當(dāng)前目錄(pwd)下的backup.tar.
執(zhí)行成功后在宿主機(jī)的當(dāng)前目錄下執(zhí)行tar xvf backup.tar
后看到看到/dbdata
備份內(nèi)容.
- 恢復(fù)
-
創(chuàng)建一個(gè)帶有數(shù)據(jù)卷的容器:
docker run -d -it -v /dbdata --name db docker.io/centos:7.2.1511
-
創(chuàng)建另外一個(gè)新的容器, 掛載db的容器, 并解壓備份文件bakup.tar到所掛載的容器卷中.
docker run --volumes-from db -v $(pwd):/backup docker.io/centos:7.2.1511 tar xvf /backup/backup.tar
這樣就將宿主機(jī)當(dāng)前目錄下的backup.tar恢復(fù)到db容器:/dbdata
路徑下了.
Dockerfile
如何使用Dockerfile構(gòu)建一個(gè)應(yīng)用程序的鏡像.
將應(yīng)用程序的jpa.jar和Dockerfile文件拷貝到/root/trainning
目錄下
Dockerfile的內(nèi)容如下:
# 指定基礎(chǔ)image, 要放在前面, 因?yàn)楹罄m(xù)的指令有依賴(lài)域這個(gè)image
FROM java:8u102-jdk
# 指定鏡像創(chuàng)建者信息
MAINTAINER thank
# 構(gòu)建指令, RUN可以運(yùn)行任何被基礎(chǔ)image支持的命令
RUN mkdir /app
# 構(gòu)建指令, ADD <src> <dest> 從宿主機(jī)的src路徑拷貝文件到容器中的dest路徑
ADD . /app
# 指定容器需要映射到宿主機(jī)器的端口
EXPOSE 8888
# 設(shè)置container啟動(dòng)時(shí)執(zhí)行的操作
ENTRYPOINT ["java","-jar","/app/jpa.jar","--spring.profiles.active=prod"]
docker build -t jpa:1.0 .
: 用當(dāng)前目錄.
中的內(nèi)容構(gòu)建一個(gè)名叫jpa:1.0的鏡像.
執(zhí)行命令后, 會(huì)看到以下輸出, 每一層都對(duì)應(yīng)Dockerfile文件中定義的指令.
Sending build context to Docker daemon 27.7 MB
Step 1 : FROM java:8u102-jdk
---> 69a777edb6dc
Step 2 : RUN mkdir /app
---> Running in 6779b11de804
---> 44fc7d80f5f6
Removing intermediate container 6779b11de804
Step 3 : ADD . /app
---> c419c4d34889
Removing intermediate container 00fa44dcbc4e
Step 4 : EXPOSE 8888
---> Running in bb4e70a56e04
---> 24e66dd52ee1
Removing intermediate container bb4e70a56e04
Step 5 : ENTRYPOINT java -jar /app/jpa.jar --spring.profiles.active=prod
---> Running in b5cbcfce01b1
---> 45e74f2c2173
Removing intermediate container b5cbcfce01b1
Successfully built 45e74f2c2173
執(zhí)行成功后, 該應(yīng)用程序鏡像就構(gòu)建出來(lái)了.
接下來(lái)可以啟動(dòng)容器來(lái)驗(yàn)證.
docker run -d --name myapp --link mysql:mysql -p 8901:8888 jpa:1.0
參數(shù)解釋:
--link mysql:mysql
前面的mysql是mysql容器名.
后面的mysql是別名, 對(duì)應(yīng)應(yīng)用程序中的spring.datasource.url=jdbc:mysql://mysql:3306/test中的mysql機(jī)器名
-p 8901:8888
前面: 對(duì)外暴露的端口號(hào)(外界訪問(wèn)的)
后面: 程序容器內(nèi)暴露的端口號(hào)
Docker-compose
Compose是Docker的服務(wù)編排工具,主要用來(lái)構(gòu)建基于Docker的復(fù)雜應(yīng)用,Compose 通過(guò)一個(gè)配置文件來(lái)管理多個(gè)Docker容器,非常適合組合使用多個(gè)容器進(jìn)行開(kāi)發(fā)的場(chǎng)景
安裝方式: https://github.com/docker/compose/releases
docker-compose up
curl -L https://github.com/docker/compose/releases/download/1.8.0-rc1/docker-compose-uname -s-uname -m > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
待續(xù)...
問(wèn)題記錄:
問(wèn)題一
systemctl start docker
時(shí)報(bào)錯(cuò)
有些機(jī)器上會(huì)出現(xiàn), 有些不會(huì)
通過(guò)systemctl status docker.service -l
查看詳細(xì)錯(cuò)誤
Error starting daemon: SELinux is not supported with the overlay2 graph driver on this kernel.
Either boot into a newer kernel or disable selinux in docker (--selinux-enabled=false)
意思是說(shuō), 此linux的內(nèi)核中的SELinux不支持 overlay2 graph driver 先匪,解決方法有兩個(gè),要么啟動(dòng)一個(gè)新內(nèi)核弃衍,要么就在docker里禁用selinux呀非,--selinux-enabled=false
解決方法:
vi /etc/sysconfig/docker
將--selinux-enabled
改為--selinux-enabled=false
問(wèn)題二
我碰到過(guò)在虛擬機(jī)中啟動(dòng)一個(gè)容器時(shí) 報(bào)出: WARNING: IPv4 forwarding is disabled. Networking will not work.
雖然容器起來(lái)了, 但是導(dǎo)致端口轉(zhuǎn)發(fā)了, 外部無(wú)法訪問(wèn):
解決辦法:
vi /etc/sysctl.conf
或者
vi /usr/lib/sysctl.d/00-system.conf
添加如下代碼:
net.ipv4.ip_forward=1
重啟network服務(wù)
systemctl restart network
查看是否修改成功
sysctl net.ipv4.ip_forward
如果返回為“net.ipv4.ip_forward = 1”則表示成功了
推薦一個(gè)解決Docker學(xué)習(xí)中的疑難雜癥: Docker問(wèn)答錄