aws-sdk-phpでs3のファイルを更新したい

$ curl -sS https://getcomposer.org/installer | php
$ php composer.phar require aws/aws-sdk-php

ファイルの読み込み

require_once “vendor/autoload.php”;

$bucket = ‘hoge’;
$key = ”;
$secret = ”;
$file = “test.txt”;

$s3client = new Aws\S3\S3Client([
‘credentials’ => [
‘key’ => $key,
‘secret’ => $secret,
],
‘region’ => ‘ap-northeast-1’,
‘version’ => ‘latest’,
]);

$s3client->registerStreamWrapper();

$stream = fopen(‘s3://hoge/test.txt’, ‘r’);
if (FALSE === $stream){
exit(“Failed to open”);
}

while (!feof($stream)){
echo fread($stream, 1024);
}

fclose($stream);
[/code]

S3のファイルの追記


require_once "vendor/autoload.php";
 
$bucket = 'hoge';
$key = 'hogehoge';
$secret = 'ccccc';
$file = "aaa.txt";
 
$s3client = new Aws\S3\S3Client([
    'credentials' => [
        'key' => $key,
        'secret' => $secret,
    ],
    'region' => 'ap-northeast-1',
    'version' => 'latest',
]);

$s3client->registerStreamWrapper();

$stream = fopen('s3://'. $bucket .'/test/' . $file, 'a');
fwrite($stream, 'hogehoge2' . PHP_EOL);
fclose($stream);

できるか不安だったけど、割と簡単に実装できて安堵

[Docker] ホストマシンのvolume mountの設定方法

ホストマシンとコンテナのボリュームをマウント

e.g.
ホストマシンの ~/work と コンテナ内の /myapp を同期させる

~/work/file1.txt
/myapp/file2.txt

ファイル名が同じだった場合、ホストマシンがコンテナを上書きする

### Dockerにおけるマウント指定
Dockerによる環境構築をする際、ボリュームをマウントする方法はDockerfile, Composeファイル、コマンドラインの3つがある

### 1. Dockerfileによるマウント
Dockerfile内でVOLUME命令を書く。この命令では、引数としてコンテナ側のディレクトリしか指定することはできない

VOLUME /myapp

Dockerfile

FROM debian
RUN mkdir /myapp && \
	echo "Hello, World" > /myapp/file.txt
VOLUME /myapp

$ sudo docker build -t hello .
$ sudo docker run -it hello bash
# cat /myapp/file.txt
Hello, World

Dockerfileにボリュームのマウント設定をする際は、ホストマシンのディレクトリを指定することができない

### 2. docker-composeによるマウント
composeファイルでは、ホストマシンのディレクトリも指定することができる

volumes:
  - ./work:/myapp

– ホストマシンのディレクトリ: Composeファイルから見た相対パスもしくは絶対パス
– コンテナのディレクトリ: 絶対パス

$ tree
.
├── docker-compose.yml
└── test
└── file.txt
$ cat test/file.txt
hello shinbashi!

docker-compose.yml

version: '3'
services:
  web:
    image: debian
    volumes:
      - ./test:/myapp

$ sudo docker-compose run web bash
Creating network “entrypoint_default” with the default driver
root@e8b020e943ae:/# cat /myapp/file.txt
hello shinbashi!
root@e8b020e943ae:/#

### DockerfileとComposeファイルを同じディレクトリに作成
$ tree
.
├── Dockerfile
├── docker-compose.yml
└── test
└── file.txt

dockerfile

FROM debian
RUN mkdir /myapp && \
	echo "It's a beautiful day." > /myapp/another_file.txt

docker-compose.yml

version: '3'
services:
  web:
    build: . 
    volumes:
      - ./test:/myapp

なるほどー、少し見えなかったものが見えてきた

[Docker] ADDとCOPYの違い

### ADD
– リモートからもファイル追加できる
– 圧縮ファイルが自動解凍

### COPY
– リモートからのファイル追加はできない
– 圧縮ファイルは自動解凍されない

FROM alpine

# auto unarchive
ADD add.txt.gz /tmp

# Can add from remote
ADD https://github.com/github/fetch/blob/master/README.md /tmp

# Not auto unarchive
COPY copy.txt.gz /tmp

なるほど、mountするときは、Add . /tmp を使って、buildする際は COPY を使うのか
少しずつ繋がっていく感じか…

[Docker] ENTRYPOINTは「必ず実行」、CMDは「デフォルト引数」

$ docker run -it centos
bashが起動する理由は、公式イメージで、/bin/bashを実行する命令があるため

CMD [“/bin/bash”]

引数の指定があれば、その引数の実行が優先される

$ docker run -it centos /bin/sh

### ENTRYPOINTが入った場合

FROM centos:latest
ENTRYPOINT ["ping", "-c", "3", "1.1.1.1"]

なるほど、ENTRYPOINTとCMDの違いがなんとなくわかったわ
ENTRYPOINTって言うと、なんか最初の引数みたいだけど、PID1の実行コマンドなのね。
奥が深いにゃー

[Docker] CMD命令とENTRYPOINT命令

CMD命令とENTRYPOINT命令はコンテナ内で実行するPID1のプロセスを指定するもの
このイメージは一体何をするのか、何のためのイメージなのかを決定づける命令

FROM debian:9
CMD ping

$ sudo docker build -t myimage .
$ sudo docker run –rm –name myimage myimage
$ sudo docker run myimage date

CMD命令とは
PID1として実行するプロセスのコマンドを指定できる
※PID1とはinitプロセスであり、起動した時に最初に実行するコマンド
そのコマンドは docker run ${image} ${引数} の引数で上書きできる

### ENTRYPOINT命令のきそ

FROM debian:9
ENTRYPOINT ["ping"]

$ sudo docker build -t myimage .
$ sudo docker run –rm –name myimage myimage 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=2 ttl=61 time=398 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=61 time=67.5 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=61 time=50.9 ms
EXEC形式で書くと、引数を渡すことができる

$ docker container run –entrypoint date myimage
エントリーポイントを上書きできる

### CMD命令とENTRYPOINT命令の組み合わせ

FROM debian:9
CMD ["8.8.8.8"]
ENTRYPOINT ["ping"]

$ sudo docker build -t myimage .
$ sudo docker run –rm –name myimage myimage
これで動く

ENTRYPOINT命令はPID1プロセスのコマンド
CMD命令はコマンドのデフォルト引数を指定できる
–entrypointで上書きできる

これは凄い、1ヶ月くらいやってもまだ理解したとは言い難い
PID1プロセスが大事なのはわかった

[Docker] ShellとExec形式

Shell形式
– 利点: 記述が簡単、シェル変数展開が利用できる
– 欠点: /bin/sh -c を渡して実行するため、イメージに /bin/sh が含まれてなければならない

Exce形式
– 利点: イメージに /bin/sh が必要ないため、イメージサイズと攻撃面を削減できる
– 欠点: 記述が面倒で、シェル変数展開できない

### Shell形式
Dockefile

FROM busybox
ENV COUNT 3
CMD /bin/ping -c $COUNT 8.8.8.8

$ sudo docker build -t test .
$ sudo docker run –rm –name test test

FROM busybox AS source
FROM scratch
COPY --from=source /bin/busybox /bin/pin
ENV COUNT 3
CMD /bin/ping -c $COUNT 8.8.8.8

### Exec形式
Exec形式は、指定のコマンドを直接実行するもの
Shell形式である必要はないが、JSOフォーマットで記述しないといけない

FROM busybox
CMD ["/bin/ping", "-c", "3", "8.8.8.8"]
FROM busybox AS source
FROM scratch
COPY --from=source /bin/busybox /bin/pin
CMD ["/bin/ping", "-c", "3", "8.8.8.8"]

EXECだとシェル変数展開ができないが、/bin/shは必要ないのね
ShellとExec形式の2種類があるってことはわかった。

[Direct Connect] Transit Gatewayとは

Transit Gatewayとは?
-> VPCとオンプレミスネットワークを相互接続するために使用できるネットワーク中継ハブ
-> 複数のVPCと接続する場合などにルーティング接続(VPC, VPN接続を指定できる)
-> オンプレミスを単一のゲートウェイで接続することができるサービス

ルートテーブルを作成し、アソシエーション、プロパゲーションし、サブネットのルートテーブルに経路を追加する

### Create transit gateway
transit gatewayを作成: transit-gateway-01
transit gateway route tableを作成: transit-gateway-route-table-01
Transit gateway attachments: VPC attachmentでVPCをattachする

なるほど、なんとなく、仕組み自体は理解した

AWS DynamoDBとは?

– Managed NoSQLデータベース(Key Value Store)
– 3つのAZに分散して格納される

### DynamoDBを触ってみる
– table作成

テーブル名: Music
パーティションキー: Artist
ソートキー(任意設定): SongTitle
Default setting
-> Create Table

### DynamoDB操作
$ aws dynamodb put-item –table-name Music –item ‘{ “Artist”: { “S”: “Ryosuke” }, “SongTitle”: { “S”: “FirstSong” }}’
$ aws dynamodb put-item –table-name Music –item ‘{ “Artist”: { “S”: “Ryosuke” }, “SongTitle”: { “S”: “SecondSong” }}’
$ aws dynamodb put-item –table-name Music –item ‘{ “Artist”: { “S”: “Michael” }, “SongTitle”: { “S”: “FirstSong” }}’

$ aws dynamodb scan –table-name Music
$ aws dynamodb get-item –table-name Music –key ‘{ “Artist”: { “S”: “Ryosuke” }, “SongTitle”: { “S”: “SecondSong” }}’
$ aws dynamodb query –table-name Music –key-condition-expression ‘Artist = :Artist’ –expression-attribute-values ‘{ “:Artist”> : { “S”: “Ryosuke” }}’

ほうほう、なるほどー
Redisみたいな感じかー

PHPのエラーログ

まず、php.iniの場所
$ php -r “echo phpinfo();” | grep “php.ini”
Configuration File (php.ini) Path => /etc/php/7.4/cli
Loaded Configuration File => /etc/php/7.4/cli/php.ini

$ cat /etc/php/7.4/cli/php.ini | grep error_log
; server-specific log, STDERR, or a location specified by the error_log
; Set maximum length of log_errors. In error_log information about the source is
;error_log = php_errors.log
;error_log = syslog
; to syslog. Only used when error_log is set to syslog.
; the message. Only used when error_log is set to syslog.
; OPcache error_log file name. Empty string assumes “stderr”.
;opcache.error_log=

あれ、コメントアウトされていて、出力されていない…?

$ sudo vi /etc/php/7.4/cli/php.ini
$ G
$ error_log = /var/log/php.log


ini_set('display_errors', "On");

$num1 = 2;
$num2 = 0;

try {
	echo calc1($num1, $num2);
} catch (Exception $e){
	echo $e->getMessage();
	error_log("[". date('Y-m-d H:i:s') . "]". "保存に失敗しました。\n", 3, "/var/www/html/debug.log");
}

function calc1($a, $b){
	if ($b == 0){
		throw new Exception("エラー");
	}
	return $a/$b;
}

$ sudo touch debug.log
$ sudo chmod 777 /var/www/html/debug.log
$ cat /var/www/html/debug.log
[2022-04-09 23:37:07]保存に失敗しました。

これで、エラーログを出力できる。

error_log("[". date('Y-m-d H:i:s') . "]". "保存に失敗しました。\n", 3, "/var/log/php.log");

なるほど、理解した。