一、Docker概述
1、Docker是什么?
使用最廣泛的開源容器引擎
一種操作系統級的虛擬化技術
依賴于Linux內核特性:Namespace(資源隔離)和Cgroups(資源限制)
一個簡單的應用程序打包工具
2、Docker基本組成
Docker Client:客戶端
Ddocker Daemon:守護進程
Docker Images:鏡像
Docker Container:容器
Docker Registry:鏡像倉庫
二、Docker安裝
1、Docker版本
社區版(Community Edition,CE)
企業版(Enterprise Edition,EE)
2、支持平臺
Linux(CentOS,Debian,Fedora,Oracle Linux,RHEL,SUSE和Ubuntu)
Mac
Windows
3、MAC系統安裝Docker
macOS 使用 Homebrew 安裝 Docker Desktop CE
系統要求:系統最低為 macOS Sierra 10.12。
安裝命令:
$ brew cask install docker
$ docker --version
三、鏡像管理
1、鏡像是什么
? 一個分層存儲的文件
? 一個軟件的環境
? 一個鏡像可以創建N個容器
? 一種標準化的交付
鏡像不是一個單一的文件,而是有多層構成。我們可以通過docker history <ID/NAME> 查看鏡像中各層內容及大小,每層 對應著Dockerfile中的一條指令。Docker鏡像默認存儲在/var/lib/docker/<storage-driver>中。
鏡像從哪里來?
Docker Hub是由Docker公司負責維護的公共注冊中心,包含大量的容器鏡像,Docker工具默認從這個公共鏡像庫下載鏡像。 地址:https://hub.docker.com/explore
配置鏡像加速器:
右鍵點擊桌面頂欄的 docker 圖標,選擇 Preferences ,在 Daemon 標簽(Docker 17.03 之前版本為 Advanced 標簽)下的 Registry mirrors 列表中將
https://yp7fjc4v.mirror.aliyuncs.com加到"registry-mirrors"的數組里,點擊 Apply & Restart按鈕,等待Docker重啟并應用配置的鏡像加速器。
2、鏡像與容器聯系
如圖,容器其實是在鏡像的最上面加了一層讀寫層,改動運行容器里的文件時, 會先從鏡像里要寫的文件復制到容器自己的文件系統中(讀寫層)。 如果容器刪除了,最上面的讀寫層也就刪除了,改動也就丟失了。所以無論多少個容器共享一個鏡像,所做的寫操作都是從鏡像的文件系統中復制過來操作的,并不會修改鏡像的源文件,這種方式提高磁盤利用率。 若想持久化這些改動,可以通過docker commit 將容器保存成一個新鏡像。
3、管理鏡像常用命令
查看docker 命令的用法:docker --help
查看管理鏡像常用命令image 的用法:docker image --help
指令 | 描述 |
---|---|
ls | 列出鏡像 |
build | 構建鏡像來自Dockerfile |
history | 查看鏡像歷史 |
inspect | 顯示一個或多個鏡像詳細信息 |
pull | 從鏡像倉庫拉取鏡像 |
push | 推送一個鏡像到鏡像倉庫 |
rm | 移除一個或多個鏡像 |
prune | 移除未使用的鏡像。沒有被標記或被任何容器引用的 |
tag | 創建一個引用源鏡像標記目標鏡像 |
export | 導出容器文件系統到tar歸檔文件 |
import | 導入容器文件系統tar歸檔文件創建鏡像 |
save | 保存一個或多個鏡像到一個tar歸檔文件 |
load | 加載鏡像來自tar歸檔或標準輸入 |
四、容器管理
1、創建容器常用選項
# docker container --help
選項 | 描述 |
---|---|
-i, –interactive | 交互式 |
-t, –tty | 分配一個偽終端 |
-d, –detach | 運行容器到后臺 |
-e, –env | 設置環境變量 |
-p, –publish list | 發布容器端口到主機 |
-P, –publish-all | 發布容器所有EXPOSE的端口到宿主機隨機端口 |
–name string | 指定容器名稱 |
-h, –hostname | 設置容器主機名 |
–ip string | 指定容器IP,只能用于自定義網絡 |
–network | 連接容器到一個網絡 |
–mount mount | 將文件系統附加到容器 |
-v, –volume list | 綁定掛載一個卷 |
–restart string | 容器退出時重啟策略,默認no,可選值:[always/on-failure] |
2、容器資源限制
選項 | 描述 |
---|---|
-m,–memory | 容器可以使用的最大內存量 |
–memory-swap | 允許交換到磁盤的內存量 |
–memory-swappiness=<0-100> | 容器使用SWAP分區交換的百分比(0-100,默認為-1) |
–oom-kill-disable | 禁用OOM Killer |
–cpus | 可以使用的CPU數量 |
–cpuset-cpus | 限制容器使用特定的CPU核心,如(0-3, 0,1) |
–cpu-shares | CPU共享(相對權重) |
3、管理容器常用命令
選項 | 描述 |
---|---|
ls | 列出容器 |
inspect | 查看一個或多個容器詳細信息 |
exec | 在運行容器中執行命令 |
commit | 創建一個新鏡像來自一個容器 |
cp | 拷貝文件/文件夾到一個容器 |
logs | 獲取一個容器日志 |
port | 列出或指定容器端口映射 |
top | 顯示一個容器運行的進程 |
stats | 顯示容器資源使用統計 |
stop/start | 停止/啟動一個或多個容器 |
rm | 刪除一個或多個容器 |
update | 表更資源的更新 |
五、管理容器里應用程序數據
Docker提供三種方式將數據從宿主機掛載到容器中:
? volumes:Docker管理宿主機文件系統的一部分(/var/lib/docker/volumes)。保存數據的最佳方式。
? bind mounts:將宿主機上的任意位置的文件或者目錄掛載到容器中。
? tmpfs:掛載存儲在主機系統的內存中,而不會寫入主機的文件系統。如果不希望將數據持久存儲在任何位置,可以使用 tmpfs,同時避免寫入容器可寫層提高性能。
1、Volume
管理卷:
# docker volume create nginx-vol
# docker volume ls
# docker volume inspect nginx-vol
用卷創建一個容器:
# docker run -d --name=nginx-test --mount src=nginx-vol,dst=/usr/share/nginx/html nginx
清理:
# docker stop nginx-test
# docker rm nginx-test
# docker volume rm nginx-vol
注意:
- 如果沒有指定卷,自動創建。
2、Bind Mounts
用卷創建一個容器:
$ mkdir -p $(pwd)/apps/wwwroot
$ docker run -d -it --name=nginx-test --mount type=bind,src=$(pwd)/apps/wwwroot,dst=/usr/share/nginx/html nginx
驗證綁定:
$ docker inspect nginx-test
清理:
$ docker stop nginx-test
$ docker rm nginx-test
注意:
- 如果源文件/目錄沒有存在,不會自動創建,會拋出一個錯誤。
- 如果掛載目標在容器中非空目錄,則該目錄現有內容將被隱藏。
六、容器網絡
網絡模式
? bridge
–net=bridge 默認網絡,Docker啟動后創建一個docker0網橋,默認創建的容器也是添加到這個網橋中。
? 自定義網絡 與默認的bridge原理一樣,但自定義網絡具備內部DNS發現,可以通過容器名或者主機名容器之間網絡通信。
? host –net=host
容器不會獲得一個獨立的network namespace,而是與宿主機共用一個。這就意味著容器不會有自己的網卡信息,而是使用宿主
機的。容器除了網絡,其他都是隔離的。
? none
–net=none
獲取獨立的network namespace,但不為容器進行任何網絡配置,需要我們手動配置。
? container
–net=container:Name/ID
與指定的容器使用同一個network namespace,具有同樣的網絡配置信息,兩個容器除了網絡,其他都還是隔離的。
七、Dockerfile
1. Dockerfile格式
從上往下執行:
FROM centos:latest
MAINTAINER liuzhousheng
RUN yum install gcc -y
COPY run.sh /usr/bin
EXPOSE 80
CMD [“run.sh”]
2. Dockerfile指令
指令 | 描述 |
---|---|
FROM | 構建新鏡像是基于哪個鏡像 |
MAINTAINER | 鏡像維護者姓名或郵箱地址 |
RUN | 構建鏡像時運行的Shell命令 |
COPY | 拷貝文件或目錄到鏡像中 |
ENV | 設置環境變量 |
USER | 為RUN、CMD和ENTRYPOINT執行命令指定運行用戶 |
EXPOSE | 聲明容器運行的服務端口 |
HEALTHCHECK | 容器中服務健康檢查 |
WORKDIR | 為RUN、CMD、ENTRYPOINT、COPY和ADD設置工作目錄 |
ENTRYPOINT | 運行容器時執行,如果有多個ENTRYPOINT指令,最后一個生效 |
CMD | 運行容器時執行,如果有多個CMD指令,最后一個生效 |
3. Build鏡像
Usage: docker build [OPTIONS] PATH | URL | - [flags] Options:
-t, --tag list # 鏡像名稱
-f, --file string # 指定Dockerfile文件位置
# docker build .
# docker build -t shykes/myapp .
# docker build -t shykes/myapp -f /path/Dockerfile /path
# docker build -t shykes/myapp http://www.example.com/Dockerfile
4. 構建Nginx,PHP基礎鏡像
? 構建Nginx基礎鏡像
FROM centos:7
MAINTAINER liuzhousheng
RUN yum install -y gcc gcc-c++ make \
openssl-devel pcre-devel gd-devel \
iproute net-tools telnet wget curl && \
yum clean all && \
rm -rf /var/cache/yum/*
RUN wget http://nginx.org/download/nginx-1.15.5.tar.gz && \
tar zxf nginx-1.15.5.tar.gz && \
cd nginx-1.15.5 &&\
./configure --prefix=/usr/local/nginx \
--with-http_ssl_module \
--with-http_stub_status_module && \
make -j 4 && make install && \
rm -rf /usr/local/nginx/html/* && \
echo "ok" >> /usr/local/nginx/html/status.html && \
cd / && rm -rf nginx-1.12.2* && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
ENV PATH $PATH:/usr/local/nginx/sbin
#COPY nginx.conf /usr/local/nginx/conf/nginx.conf ## 先注釋這行,不然構建需要依賴本地配置文件,啟動啟動容器會依賴php
WORKDIR /usr/local/nginx
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
運行命令:
# docker build -t nginx:v1 -f dockerfile-nginx .
# docker image ls
# docker run -d --name nginx01 -p 88:80 nginx:v1
# docker ps -l
# curl 10.40.6.165:88/status.html
用剛剛創建的nginx:v1 鏡像在創建一個v2鏡像
# cat index.html ## 將這文件作為nginx root目錄
hello docker!!!
# cat dockerfile-nginxv2 ## 新的dockerfile
FROM nginx:v1
COPY index.html /usr/local/nginx/html/
# docker build -t nginx:v2 -f dockerfile-nginxv2 . ## 創建nginx:v2鏡像
Sending build context to Docker daemon 410.1kB
Step 1/2 : FROM nginx:v1
---> db3cfa07d4a5
Step 2/2 : COPY index.html /usr/local/nginx/html
---> 64f743ec5b18
Successfully built 64f743ec5b18
Successfully tagged nginx:v2
# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx v2 64f743ec5b18 27 seconds ago 395MB
nginx v1 db3cfa07d4a5 11 minutes ago 395MB
# docker run -d --name nginx02 -p 89:80 nginx:v2
c446b345b73ac6417d7090b5d46c7be574b87be152ad7c9f42886e86e43f4d06
# curl 10.40.6.165:89
hello docker!!!
? 構建PHP基礎鏡像
FROM centos:7
MAINTAINER liuzhousheng
RUN yum install epel-release -y && \
yum install -y gcc gcc-c++ make gd-devel libxml2-devel \
libcurl-devel libjpeg-devel libpng-devel openssl-devel \
libmcrypt-devel libxslt-devel libtidy-devel autoconf \
iproute net-tools telnet wget curl && \
yum clean all && \
rm -rf /var/cache/yum/*
RUN wget http://docs.php.net/distributions/php-5.6.36.tar.gz && \
tar zxf php-5.6.36.tar.gz && \
cd php-5.6.36 && \
./configure --prefix=/usr/local/php \
--with-config-file-path=/usr/local/php/etc \
--enable-fpm --enable-opcache \
--with-mysql --with-mysqli --with-pdo-mysql \
--with-openssl --with-zlib --with-curl --with-gd \
--with-jpeg-dir --with-png-dir --with-freetype-dir \
--enable-mbstring --with-mcrypt --enable-hash && \
make -j 4 && make install && \
cp php.ini-production /usr/local/php/etc/php.ini && \
cp sapi/fpm/php-fpm.conf /usr/local/php/etc/php-fpm.conf && \
sed -i "90a \daemonize = no" /usr/local/php/etc/php-fpm.conf && \
mkdir /usr/local/php/log && \
cd / && rm -rf php* && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
ENV PATH $PATH:/usr/local/php/sbin:/usr/local/php/bin
COPY php.ini /usr/local/php/etc/
COPY php-fpm.conf /usr/local/php/etc/
WORKDIR /usr/local/php
EXPOSE 9000
CMD ["php-fpm"]
運行命令構建:
# docker build -t php:v1 -f dockerfile-php .
# docker image ls
# docker run -d --name php01 php:v1
# docker ps -l
八、快速搭建LNMP網站平臺
lnmp 架構要用到三個容器,所以要準備相應的三個鏡像:
php: php:v1(上邊我們自己制作的鏡像)
nginx: nginx:v1(上邊我們自己制作的鏡像)
mysql: mysql:5.7(使用官方鏡像)
# docker pull mysql:5.7
(1)、自定義網絡
# docker network create net-lnmp
(2)、創建Mysql容器
$ mkdir -p /Users/liuzhousheng/docker/data/mysql
$ docker run -d --name lnmp_mysql --net net-lnmp --mount type=bind,src=/Users/liuzhousheng/docker/data/mysql,dst=/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress mysql:5.7 --character-set-server=utf8
(3)、創建PHP容器
$ mkdir -p ~/apps/wwwroot
$ docker run -d --name lnmp_php --net net-lnmp --mount type=bind,src=/Users/liuzhousheng/apps/wwwroot,dst=/wwwroot php:v1
(4)、創建Nginx容器
nginx.conf配置文件:
user nobody;
worker_processes 4;
worker_rlimit_nofile 65535;
error_log logs/error.log notice;
pid /var/run/nginx.pid;
events {
use epoll;
worker_connections 4096;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log off;
keepalive_timeout 65;
client_max_body_size 64m;
server {
listen 80;
server_name www.lnmp_test.com;
index index.php index.html;
access_log logs/www.lnmp_test.com_access.log;
error_log logs/www.lnmp_test.com_error.log;
# location ~ .*\.(js|css|html|png|gif|jpg|jpeg)$ {
location / {
root /wwwroot;
}
location ~* \.php$ {
root /wwwroot;
fastcgi_pass lnmp_php:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
}
啟動容器:
$ mkdir -p /Users/liuzhousheng/apps/logs/wordpress/nginx
$ docker run -d --name lnmp_nginx --net net-lnmp -p 88:80 --mount type=bind,src=$(pwd)/nginx.conf,dst=/usr/local/nginx/conf/nginx.conf --mount type=bind,src=/Users/liuzhousheng/apps/wwwroot,dst=/wwwroot --mount type=bind,src=/Users/liuzhousheng/apps/logs/wordpress/nginx,dst=/usr/local/nginx/logs nginx:v1
查看三個容器:
# docker ps
創建php測試頁:
$cat ~/apps/wwwroot/test.php
<?php
phpinfo()
?>
## 瀏覽器請求URL:http://10.40.6.165:88/test.php
(5)、以wordpress博客為例
https://cn.wordpress.org/wordpress-4.9.4-zh_CN.tar.gz
# cd ~/apps/wwwroot
# wget https://cn.wordpress.org/wordpress-4.9.4-zh_CN.tar.gz
# tar xvf wordpress-4.9.4-zh_CN.tar.gz
使用瀏覽器訪問 http://10.40.6.165:88/wordpress
進入容器 lnmp_nginx查看nginx訪問日志:
# docker exec -it lnmp_nginx bash
[root@f8c38e7b7a95 nginx]# tail -f logs/www.lnmp_test.com_access.log
10.19.1.28 - - [15/May/2019:17:13:42 +0800] "POST /wordpress/wp-admin/admin-ajax.php HTTP/1.1" 200 58 "http://10.40.6.165:88/wordpress/wp-admin/edit.php" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36"
10.19.1.28 - - [15/May/2019:17:13:43 +0800] "GET /wordpress/wp-includes/js/wp-emoji-release.min.js?ver=4.9.10 HTTP/1.1" 304 0 "http://10.40.6.165:88/wordpress/wp-admin/edit.php" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36"
10.19.1.28 - - [15/May/2019:17:13:43 +0800] "GET /wordpress/wp-admin/edit.php HTTP/1.1" 200 48058 "http://10.40.6.165:88/wordpress/wp-admin/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36"
10.19.1.28 - - [15/May/2019:17:13:43 +0800] "POST /wordpress/wp-admin/admin-ajax.php HTTP/1.1" 200 58 "http://10.40.6.165:88/wordpress/wp-admin/edit.php" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36"