1 Pembuatan Image MySQL-Server (Docker) Husni A. Container tak persisten B. Container persisten dengan Data Volume C. Container persisten dengan Data-...
A. Container tak persisten B. Container persisten dengan Data Volume C. Container persisten dengan Data-only Container A. Container Tak Persisten 1. Buat direktori bernama "mysql-server", cd (masuk) ke dalam direktori tersebut. 2. Buat file Dockerfile dengan isi sebagai berikut: #Dockerfile untuk membuat Image MySQL server FROM ubuntu RUN apt-get update && apt-get -y install mysql-client mysql-server RUN sed -i 's/^bind-address/#bind-adress/g' /etc/mysql/my.cnf RUN /etc/init.d/mysql start && echo "GRANT ALL ON *.* TO admin@'%' IDENTIFIED BY 'admin123' WITH GRANT OPTION; FLUSH PRIVILEGES" | mysql -u root EXPOSE 3306 CMD ["/usr/bin/mysqld_safe"]
Catatan: Baris RUN sed -i 's/^bind-address/#bind-adress/g' /etc/mysql/my.cnf dapat diganti dengan ADD ./my.cnf /etc/mysql/my.cnf. Ini dilakukan terutama jika ada banyak baris konfigurasi di dalam file my.cnf. 3. Buat image dengan perintah docker build dan jalankan: docker build -t img-mysqlserver . docker run -d -p 3306:3306 img-mysqlserver
4. Menguji MySQL Server. Kita dapat mengakses MySQL Server tersebut, baik dari Host maupun container lain memanfaatkan socket TCP (port 3306): # lsof -i :3306 COMMAND PID USER docker 11267 root
FD 4u
TYPE DEVICE SIZE/OFF NODE NAME IPv6 51821 0t0 TCP *:mysql (LISTEN)
Bagaimana dengan persistensi? Apakah semua data dan perubahan terhadapnya tetap tersimpan meskipun container telah di-stop? INGAT semua data yang di-update di dalam container TIDAK tersimpan di dalam image. Ada 2 cara untuk membuat perubahan data di dalam Container menjadi persisten (tetap ada meski container telah tiada):
Data volumes: A data volume is a specially-designated directory within one or more containers that bypasses the Union File System to provide several useful features for persistent or shared data
Data volume containers: If you have some persistent data that you want to share between containers, or want to use from non-persistent containers, it's best to create a named Data Volume Container, and then to mount the data from it.
Lebih detailnya, silakan akses panduan di https://docs.docker.com/userguide/dockervolumes/
B. Container Persisten dengan Data Volume Jika image mysql-server di atas dijalankan dengan menggunakan parameter -v: docker run -d -p 3306:3306 -v /data/mysql:/var/lib/mysql img-mysqlserver
maka akan mengakibatkan terhapusnya data sistem dari mysql (tabel-tabel dengan metadatanya), SOLUSINYA? Berikut ini adalah langkah-langkah membuat image (moyangnya container) yang mampu menyediakan persistensi data: 1. Membuat Skrip Inisiasi Ulang Database Kita harus membuat script untuk menginisiasi ulang database dimana sudah tidak ada metadata yang tersedia. Skrip ini dapat ditambahkan ke dalam Dockerfile dengan perintah ADD. #!/bin/bash #script run.sh untuk inisiasi ulang metadata database mysql #jika direktori /data/mysql belum ada, database kosong if [ ! -d /data/mysql ]; then #setup mysqldb mysql_install_db --datadir=/data/mysql echo "=> Starting MySQL." /usr/bin/mysqld_safe --datadir=/data/mysql > /dev/null 2>&1 & RET=1 while [[ $RET -ne 0 ]]; do echo "=> Waiting for confirmation of MySQL service startup" sleep 5 mysql -uroot -e "status" > /dev/null 2>&1 RET=$? done
2
PASS='admin123' echo "=> Creating MySQL user." mysql -uroot -e "CREATE USER 'admin'@'%' IDENTIFIED BY '$PASS'" mysql -uroot -e "GRANT ALL PRIVILEGES ON *.* TO 'admin'@'%' \ WITH GRANT OPTION" echo "=> Shutting down after setup." mysqladmin -uroot shutdown #jika /data/mysql telah ada, database telah ada else echo "=> continuing with an existing mysql setup" fi echo "=> Running MySQL Server" exec mysqld_safe --datadir=/data/mysql
2. Membuat Dockerfile Berikut ini adalah Dockerfile (versi revisi) yang memanggil script run.sh: #Dockerfile #File skrip yang dipanggil bernama run.sh FROM ubuntu:14.04 RUN apt-get update && apt-get -y install mysql-client mysql-server VOLUME ["/data"] ADD my.cnf /etc/mysql/conf.d/my.cnf ADD run.sh /run.sh RUN chmod +x run.sh EXPOSE 3306 ENTRYPOINT ["/run.sh"]
3. Buat file my.cnf yang menyimpan konfigurasi MySQL. Secara default, MySQL server hanya menerima koneksi dari localhost. Baris bindaddress=0.0.0.0 memungkinkan MySQL server menerima koneksi dari manapun. #my.cnf [mysqld] bind-address=0.0.0.0
Jadi ada 3 file di dalam direktori ~/husni/mysql-server: Dockerfile, my.cnf dan run.sh. 4. Membuat image, misalnya bernama img-mypersistentserver dengan perintah build. docker build -t img-mypersistentserver .
5. Membuat direktori penampung data persistent dari MySQL server, misalnya ~/docker/mydata: mkdir ~/docker/mydata
3
6. Menjalankan image img-mypersistentserver dengan run berikut: docker run -d -p 3306:3306 -v mysqlserver img-mypersistentserver
~/docker/mydata/:/data/
--name
co-
7. Pengujian: Mengakses database tersebut, membuat database, tabel dan memasukkan beberapa baris data.
Membuat container dari salah satu image yang mempunyai program client mysql (misalnya image img-mypersistentserver) dan bangun koneksi ke MySQL server tersebut (password: "admin123"): docker run -it --name co-mysqlclient --link co-mysqlserver:db \ --entrypoint="mysql" img-mypersistentserver -u admin -p -h db
Membuat database db_01 dan tabel tb_01 Berikut ini adalah contoh hasil eksekusi perintah di atas (serta langkah-langkah pembuatan database db_01 dan tabel tb_01): Enter password: "admin123" Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 Server version: 5.5.41-0ubuntu0.14.04.1 (Ubuntu) Type 'help;' statement.
or
'\h'
for
help.
Type
'\c'
to
clear
the
current
input
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | +--------------------+ 3 rows in set (0.00 sec) mysql> create database db_01; Query OK, 1 row affected (0.00 sec) mysql> use db_01; Database changed mysql> show tables; Empty set (0.00 sec) mysql> CREATE TABLE tb_01 (No INT, Nama VARCHAR(100), Email VARCHAR(100)); Query OK, 0 rows affected (0.11 sec) mysql> INSERT INTO tb_01 VALUES '[email protected]'), (2, 'Muda Intan', 'Azzam Altaf', '[email protected]'), (4, '[email protected]'); Query OK, 4 rows affected (0.42 sec) Records: 4 Duplicates: 0 Warnings: 0
mysql> show tables; +---------------------+ | Tables_in_db_docker | +---------------------+ | tb_01 | +---------------------+ 1 row in set (0.00 sec) mysql> SELECT * FROM tb_01 WHERE Email LIKE '%gmail.com'; +------+-------------------+---------------------+ | No | Nama | Email | +------+-------------------+---------------------+ | 3 | Azzam Altaf | [email protected] | | 4 | Rohmi Nur Hidayah | [email protected] | +------+-------------------+---------------------+ 2 rows in set (0.00 sec) mysql> quit; Bye
Sekarang telah keluar dari program mysql dan container co-mysqlclient. Hapus container co-mysqlclient (docker rm co-mysqlclient). Apakah data tersebut benar-benar tersimpan di dalam ~/docker/mydata? (persisten). Mari coba login lagi ke server MySQL:
Mengakses MySQL Server (lagi). Jalankan kembali container bernama co-mysqlclient (panah ke atas + Enter). mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | db_01 | | mysql | | performance_schema | +--------------------+ 4 rows in set (0.04 sec)
Ternyata data tetap ada di MySQL, tidak hilang walaupun container telah ditutup/distop! 8. Pengujian: Mengakses database MySQL dari aplikasi PHP
Buat file PHP sederhana (misal: index.php), misalnya:
5
// Create connection $conn = new mysqli($servername, $username, $password, $dbname); // Check connection if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } $sql = "SELECT No, Nama, Email FROM tb_01"; $result = $conn->query($sql); if ($result->num_rows > 0) { // output data of each row while($row = $result->fetch_assoc()) { echo "No: " . $row["No"]. " - Nama: " . $row["Nama"]. " " . $row["Email"]. " "; } } else { echo "0 results"; } $conn->close(); ?>
Simpan file tersebut ke dalam ~/docker/webdata/.
Jalankan image img-webserver yang telah dibuat sebelumnya: sudo docker run -d -v ~/docker/webdata:/var/www -p 80:80 \ --name co-testweb img-webserver
Buka web browser, akses ke IP_ADDRESS_HOST atau Nama_Host. Gambar berikut memperlihatkan hasil pada web browser Firefox:
Memanfaatkan link. Hentikan (stop) dan hapus container co-testweb tersebut. Coba jalankan image imgwebserver dengan cara berikut: sudo docker run -d -v ~/docker/webdata:/var/www \ --link co-mysqlserver:db -p 80:80 --name co-testweb img-webserver
Kemudian edit file index.php dan ganti baris: $servername = "IP_ADDRESS_HOST";
menjadi: $servername = "db";
Buka web browser, akses ke IP_ADDRESS_HOST. Perhatikan apa yang terjadi! 6
C. Container Persisten dengan Data-only Container Pada pendekatan Data Volume, container MySQL-Server langsung mengakses direktori ~/docker/mydata memanfaatkan parameter -v. Pada teknik Data-only Container, sebuah container khusus menangani Data (tidak selain data) disiapkan terlebih dahulu. Semua akses ke Data Volume harus dilakukan via container data-only tersebut. Keuntungan utama adalah portabilitas (kata Docker). Langkah-langkah pembuatan imagenya hampir sama dengan sebelumnya, berikut ini adalah contohnya: 1. Lakukan seperti bagian B sehingga ada satu direktori yang berisi 3 file: Dockerfile, run.sh dan my.cnf. Pastikan juga adanya direktori data ~/docker/mydata. 2. Buat image, misalnya bernama img-mypersistentserver2: sudo docker build -t img-mypersistentserver2 .
3. Jalankan image tertentu (misalnya: ubuntu saja) untuk membuat Data-only container: sudo docker run -d -v ~/docker/mydata:/data --name co-dataonly \ ubuntu:14.04 true
4. Jalankan image img-mypersistentserver2 dan akses ~/docker/mydata via Data-only container co-dataonly: sudo docker run -d --volumes-from co-dataonly \ --name co-mysqlserver \ img-mypersistentserver2
Catatan: Perhatikan opsi khusus --volumes-from. Kita meminta container co- mysqlserver menggunakan data volume dari container bernama co-dataonly, yaitu container Dataonly. Sesungguhnya yang terjadi adalah direktori ~/docker/mydata hadir sebagai /data di dalam container co- mysqlserver. Skrip run.sh membuat ulang database mysql sehingga jika kita menghapus container, data tetap ada di sana. Itulah pentingnya direktori /data/mysql :). Kita dapat melihat apakah container co- mysqlserver berjalan dengan sudo docker ps. Kita juga dapat melihat apa yang terjadi dalam container tersebut dengan sudo docker log -f co-mysqlserver. Apa yang terlihat adalah pesan yang dikeluarkan oleh skrip run.sh dan setup. Tekan Ctrl+C untuk keluar dari tampilan log tersebut. Anehnya, kita tidak melihat container co-dataonly dalam status running. That's alright, memang tidak harus berjalan. Kita dapat melihat bahwa co-dataonly ada dengan menjalankan perintah sudo docker ps -a.
7
5. Pengujian
Mengakses MySQL Server: membuat database dan tabel Jalankan image img-mypersistentserver (atau image lain yang ada program mysql di dalamnya) menjadi container (untuk digunakan secara interaktif) dengan memanfaatkan parameter --link: sudo docker run -it --link co-mysqlserver:db --name co-mysqlclient \ --entrypoint="mysql" img-mypersistentserver -u admin -p -h db
Masukkan "admin123" sebagai password sehingga diperoleh prompt mysql>. Seperti sebelumnya, database db_01 dan tabel tb_01 dapat dibuatkan sebagai percobaan. mysql> create database db_01 Query OK, 1 row affected (0.02 sec)
Masukkan beberapa baris record ke dalam tb_01. Jika telah selesai, silakan keluar dari bash dan containernya. Jika perlu, hapus container co-mysqlclient. Catatan: Kita melewatkan dua opsi kepada perintah docker run (di atas). Pertama --link, kedua --entrypoint. Di dalam Dockerfile dari image img-mypersistentserver2, kita menyebutkan run.sh sebagai ENTRYPOINT sehingga skrip run.sh berjalan saat container dimulai. Di sini kita membuat agar program mysql dijalankan sebagai ganti run.sh atau dengan kata lain menggantikan entrypoint default. Opsi --entrypoint juga dapat digunakan sebagai sarana troubleshoot/melihat ke dalam container. Kita dapat menggunakan bash sebagai --entrypoint dan menggunakannya. Sebagai contoh: sudo docker run -i -t --entrypoint="bash" mysql -i
...dan kita berada console pada container.
Jalankan image Web server (apache2 + php5): sudo docker run -d -v ~/docker/webdata:/var/www \ --link co-mysqlserver:db -p 80:80 --name co-testweb img-webserver
Buka web browser dan akses http://IP_ADDRES_HOST dan perhatikan apa yang terjadi?!