[{"data":1,"prerenderedAt":6516},["ShallowReactive",2],{"tag-docker-1":3},{"count":4,"content":5},5,[6,835,2660,4651,5979],{"id":7,"title":8,"body":9,"category":819,"createdAt":821,"description":822,"extension":823,"index":824,"meta":825,"navigation":94,"path":826,"publish":94,"seo":827,"series":824,"seriesTitle":824,"stem":828,"tag":829,"thumbnail":833,"updatedAt":821,"__hash__":834},"articles\u002Farticles\u002Faws-sam-disconnect-dymamodb-local.md","AWS SAMで作ったLamdaコードがローカルのDynamoDBに接続できないときの対処",{"type":10,"value":11,"toc":812},"minimark",[12,16,19,30,33,44,47,50,55,58,222,233,572,575,581,584,591,594,597,602,610,625,628,632,635,753,756,762,768,802,805,808],[13,14,15],"p",{},"こんにちはjunです。最近はこの静的ブログに動的な機能を追加するために、サーバーレス環境でのサービス開発を行っています。API gateway をトリガーとしてAWS Lambdaでコードを実行してDynamoDBで内容を保存するといったよくある構成で開発をしていました。",[13,17,18],{},"AWS Lambdaはweb上でもコードを書いて実行できますが、できたらローカル上でコードを書いてテストしてからデプロイしたいです。特に更新や改修の時はローカルで検証できることが好ましいです。",[13,20,21,22,29],{},"AWSはその辺も考えており、",[23,24,28],"a",{"href":25,"rel":26},"https:\u002F\u002Fdocs.aws.amazon.com\u002Fja_jp\u002Fserverless-application-model\u002Flatest\u002Fdeveloperguide\u002Fwhat-is-sam.html",[27],"nofollow","AWS SAM(serverless application model)"," を用意してくれています。私も開発ではこのSAMを使用してローカルで構築後、テストして本番に適用しています。",[13,31,32],{},"ひとまずチュートリアルのデプロイができたので、DynamoDBを用いた環境をローカルに作ってコードをテストすることにしました。しかし、DynamoDBをscanする処理でいつもストップし、",[34,35,40],"pre",{"className":36,"code":38,"language":39},[37],"language-text","Inaccessible host: `127.0.0.1' at port `8000'. This service may not be available in the `ap-north-east1' region.\n","text",[41,42,38],"code",{"__ignoreMap":43},"",[13,45,46],{},"というメッセージでDynamoDBに接続できませんでした。ちなみにDynamoDBの環境はDockerを用いてローカルで構築しており、localost:8000に待機していました。DynamoDBのコンテナは起動しているのに、どうして接続できないのか悩んでいました。",[13,48,49],{},"結論を言うとDockerのネットワークの設定が間違っていたからです。詳細を解説します。",[51,52,54],"h2",{"id":53},"lambdaのコードとdynamodbのコンテナ設定","LambdaのコードとDynamoDBのコンテナ設定",[13,56,57],{},"DynamoDBはこちらのDocker imageを使用して、以下の設定を用いていました。（参考サイトからのコピペです...)",[34,59,64],{"className":60,"code":61,"filename":62,"language":63,"meta":43,"style":43},"language-yaml shiki shiki-themes material-theme-ocean","version: \"3\"\n\nservices:\n  dynamodb-local:\n    container_name: dynamodb-local\n    image: amazon\u002Fdynamodb-local\n    ports:\n      - 8000:8000\n    command: -jar DynamoDBLocal.jar -dbPath \u002Fdata -sharedDb\n    volumes:\n      - .\u002Fdata:\u002Fdata\n    networks:\n      - lambda-local\nnetworks:\n  lambda-local:\n    external: true\n","docker-compose.yml","yaml",[41,65,66,89,96,105,113,123,134,142,151,162,170,178,186,194,202,210],{"__ignoreMap":43},[67,68,71,75,79,82,86],"span",{"class":69,"line":70},"line",1,[67,72,74],{"class":73},"s-wAU","version",[67,76,78],{"class":77},"sAklC",":",[67,80,81],{"class":77}," \"",[67,83,85],{"class":84},"sfyAc","3",[67,87,88],{"class":77},"\"\n",[67,90,92],{"class":69,"line":91},2,[67,93,95],{"emptyLinePlaceholder":94},true,"\n",[67,97,99,102],{"class":69,"line":98},3,[67,100,101],{"class":73},"services",[67,103,104],{"class":77},":\n",[67,106,108,111],{"class":69,"line":107},4,[67,109,110],{"class":73},"  dynamodb-local",[67,112,104],{"class":77},[67,114,115,118,120],{"class":69,"line":4},[67,116,117],{"class":73},"    container_name",[67,119,78],{"class":77},[67,121,122],{"class":84}," dynamodb-local\n",[67,124,126,129,131],{"class":69,"line":125},6,[67,127,128],{"class":73},"    image",[67,130,78],{"class":77},[67,132,133],{"class":84}," amazon\u002Fdynamodb-local\n",[67,135,137,140],{"class":69,"line":136},7,[67,138,139],{"class":73},"    ports",[67,141,104],{"class":77},[67,143,145,148],{"class":69,"line":144},8,[67,146,147],{"class":77},"      -",[67,149,150],{"class":84}," 8000:8000\n",[67,152,154,157,159],{"class":69,"line":153},9,[67,155,156],{"class":73},"    command",[67,158,78],{"class":77},[67,160,161],{"class":84}," -jar DynamoDBLocal.jar -dbPath \u002Fdata -sharedDb\n",[67,163,165,168],{"class":69,"line":164},10,[67,166,167],{"class":73},"    volumes",[67,169,104],{"class":77},[67,171,173,175],{"class":69,"line":172},11,[67,174,147],{"class":77},[67,176,177],{"class":84}," .\u002Fdata:\u002Fdata\n",[67,179,181,184],{"class":69,"line":180},12,[67,182,183],{"class":73},"    networks",[67,185,104],{"class":77},[67,187,189,191],{"class":69,"line":188},13,[67,190,147],{"class":77},[67,192,193],{"class":84}," lambda-local\n",[67,195,197,200],{"class":69,"line":196},14,[67,198,199],{"class":73},"networks",[67,201,104],{"class":77},[67,203,205,208],{"class":69,"line":204},15,[67,206,207],{"class":73},"  lambda-local",[67,209,104],{"class":77},[67,211,213,216,218],{"class":69,"line":212},16,[67,214,215],{"class":73},"    external",[67,217,78],{"class":77},[67,219,221],{"class":220},"sbqyR"," true\n",[13,223,224,225,228,229,232],{},"上記の",[41,226,227],{},"- 8000:8000"," の通りlocalhostの8000にDynamoDBのエンドポイントが待機しています。\n",[41,230,231],{},"docker-compose up","してこの記述の通り、Lambdaのコードで以下のように記述しました。",[34,234,239],{"className":235,"code":236,"filename":237,"language":238,"meta":43,"style":43},"language-js shiki shiki-themes material-theme-ocean","const AWS = require('aws-sdk')\nlet response;\n\nvar dynamoOpt = {\n    endpoint: \"http:\u002F\u002Flocalhost:8000\",\n};\n\nexports.lambdaHandler = async (event, context) => {\n    let params = {\n            TableName:'table',\n        };\n\n        try{\n            const result = await dynamodb.scan(params).promise()\n            return {\n                statusCode: 200,\n                body: JSON.stringify(result.Items),\n            };\n        }catch (e){\n            return {\n                statusCode: 500,\n                body: e.message,\n            };\n        }\n}\n","app.js","js",[41,240,241,272,283,287,300,318,323,327,362,374,390,395,399,408,445,452,465,495,501,519,526,538,555,560,566],{"__ignoreMap":43},[67,242,243,247,251,254,258,261,264,267,269],{"class":69,"line":70},[67,244,246],{"class":245},"sJ14y","const",[67,248,250],{"class":249},"s0W1g"," AWS ",[67,252,253],{"class":77},"=",[67,255,257],{"class":256},"sdLwU"," require",[67,259,260],{"class":249},"(",[67,262,263],{"class":77},"'",[67,265,266],{"class":84},"aws-sdk",[67,268,263],{"class":77},[67,270,271],{"class":249},")\n",[67,273,274,277,280],{"class":69,"line":91},[67,275,276],{"class":245},"let",[67,278,279],{"class":249}," response",[67,281,282],{"class":77},";\n",[67,284,285],{"class":69,"line":98},[67,286,95],{"emptyLinePlaceholder":94},[67,288,289,292,295,297],{"class":69,"line":107},[67,290,291],{"class":245},"var",[67,293,294],{"class":249}," dynamoOpt ",[67,296,253],{"class":77},[67,298,299],{"class":77}," {\n",[67,301,302,305,307,309,312,315],{"class":69,"line":4},[67,303,304],{"class":73},"    endpoint",[67,306,78],{"class":77},[67,308,81],{"class":77},[67,310,311],{"class":84},"http:\u002F\u002Flocalhost:8000",[67,313,314],{"class":77},"\"",[67,316,317],{"class":77},",\n",[67,319,320],{"class":69,"line":125},[67,321,322],{"class":77},"};\n",[67,324,325],{"class":69,"line":136},[67,326,95],{"emptyLinePlaceholder":94},[67,328,329,332,335,338,341,344,348,351,354,357,360],{"class":69,"line":144},[67,330,331],{"class":77},"exports.",[67,333,334],{"class":256},"lambdaHandler",[67,336,337],{"class":77}," =",[67,339,340],{"class":245}," async",[67,342,343],{"class":77}," (",[67,345,347],{"class":346},"s7ZW3","event",[67,349,350],{"class":77},",",[67,352,353],{"class":346}," context",[67,355,356],{"class":77},")",[67,358,359],{"class":245}," =>",[67,361,299],{"class":77},[67,363,364,367,370,372],{"class":69,"line":153},[67,365,366],{"class":245},"    let",[67,368,369],{"class":249}," params",[67,371,337],{"class":77},[67,373,299],{"class":77},[67,375,376,379,381,383,386,388],{"class":69,"line":164},[67,377,378],{"class":73},"            TableName",[67,380,78],{"class":77},[67,382,263],{"class":77},[67,384,385],{"class":84},"table",[67,387,263],{"class":77},[67,389,317],{"class":77},[67,391,392],{"class":69,"line":172},[67,393,394],{"class":77},"        };\n",[67,396,397],{"class":69,"line":180},[67,398,95],{"emptyLinePlaceholder":94},[67,400,401,405],{"class":69,"line":188},[67,402,404],{"class":403},"s6cf3","        try",[67,406,407],{"class":77},"{\n",[67,409,410,413,416,418,421,424,427,430,432,435,437,439,442],{"class":69,"line":196},[67,411,412],{"class":245},"            const",[67,414,415],{"class":249}," result",[67,417,337],{"class":77},[67,419,420],{"class":403}," await",[67,422,423],{"class":249}," dynamodb",[67,425,426],{"class":77},".",[67,428,429],{"class":256},"scan",[67,431,260],{"class":73},[67,433,434],{"class":249},"params",[67,436,356],{"class":73},[67,438,426],{"class":77},[67,440,441],{"class":256},"promise",[67,443,444],{"class":73},"()\n",[67,446,447,450],{"class":69,"line":204},[67,448,449],{"class":403},"            return",[67,451,299],{"class":77},[67,453,454,457,459,463],{"class":69,"line":212},[67,455,456],{"class":73},"                statusCode",[67,458,78],{"class":77},[67,460,462],{"class":461},"sx098"," 200",[67,464,317],{"class":77},[67,466,468,471,473,476,478,481,483,486,488,491,493],{"class":69,"line":467},17,[67,469,470],{"class":73},"                body",[67,472,78],{"class":77},[67,474,475],{"class":249}," JSON",[67,477,426],{"class":77},[67,479,480],{"class":256},"stringify",[67,482,260],{"class":73},[67,484,485],{"class":249},"result",[67,487,426],{"class":77},[67,489,490],{"class":249},"Items",[67,492,356],{"class":73},[67,494,317],{"class":77},[67,496,498],{"class":69,"line":497},18,[67,499,500],{"class":77},"            };\n",[67,502,504,507,510,512,515,517],{"class":69,"line":503},19,[67,505,506],{"class":77},"        }",[67,508,509],{"class":403},"catch",[67,511,343],{"class":73},[67,513,514],{"class":249},"e",[67,516,356],{"class":73},[67,518,407],{"class":77},[67,520,522,524],{"class":69,"line":521},20,[67,523,449],{"class":403},[67,525,299],{"class":77},[67,527,529,531,533,536],{"class":69,"line":528},21,[67,530,456],{"class":73},[67,532,78],{"class":77},[67,534,535],{"class":461}," 500",[67,537,317],{"class":77},[67,539,541,543,545,548,550,553],{"class":69,"line":540},22,[67,542,470],{"class":73},[67,544,78],{"class":77},[67,546,547],{"class":249}," e",[67,549,426],{"class":77},[67,551,552],{"class":249},"message",[67,554,317],{"class":77},[67,556,558],{"class":69,"line":557},23,[67,559,500],{"class":77},[67,561,563],{"class":69,"line":562},24,[67,564,565],{"class":77},"        }\n",[67,567,569],{"class":69,"line":568},25,[67,570,571],{"class":77},"}\n",[13,573,574],{},"そしてビルドしてテストをしても",[34,576,579],{"className":577,"code":578,"language":39},[37],"sam build\nsam local invoke -e events\u002Fevent.json\n\nInaccessible host: `127.0.0.1' at port `8000'. This service may not be available in the `ap-north-east1' region.\n",[41,580,578],{"__ignoreMap":43},[13,582,583],{},"とDynamoDBのホストに接続できていないというエラーが発生しました。色々検索した結果、以下の記事がキーとなり解決しました。",[13,585,586],{},[23,587,590],{"href":588,"rel":589},"https:\u002F\u002Ffuture-architect.github.io\u002Farticles\u002F20200323\u002F",[27],"Serverless連載1: SAMを使ったローカルテスト（Go編）",[51,592,593],{"id":593},"解決法",[13,595,596],{},"上記記事の図をみて一気に理解できました。原因はSAMのコンテナがDynamoDBのコンテナに接続できず、またホスト（localhost)の指定が間違っていたからです。",[598,599,601],"h3",{"id":600},"samもdockerで実行されている","SAMもdockerで実行されている",[13,603,604,605],{},"SAMは自動デプロイだけでなく、ローカルでのテストもサポートしています。",[23,606,609],{"href":607,"rel":608},"https:\u002F\u002Fdocs.aws.amazon.com\u002Fja_jp\u002Fserverless-application-model\u002Flatest\u002Fdeveloperguide\u002Fserverless-sam-cli-install-linux.html#serverless-sam-cli-install-linux-docker",[27],"テストではDockerを用いることがドキュメントにも書かれています。",[13,611,612,613,616,617,620,621,624],{},"LambdaのコードはDockerのあるコンテナにて実行されることになります。そのため、",[41,614,615],{},"localhost:8000","というのは私のホストOSの8000ポートでなく、SAMが実行されている環境の8000ポートに向いていたのです。SAMコンテナ内の",[41,618,619],{},"locahost:8000","にはDynamoDBなんてありませんから、",[41,622,623],{},"Inaccessible host"," になるのは当たり前です。",[13,626,627],{},"つまりやることはSAMコンテナネットワークと、DynamoDBコンテナネットワークを接続してあげる必要があります。",[598,629,631],{"id":630},"dynamodbの設定とテスト実行時の引数を与える","DynamoDBの設定とテスト実行時の引数を与える",[13,633,634],{},"先ほどのDynamoDBのdocker-compose.yamlを見てみると、ネットワークの設定があります。",[34,636,638],{"className":60,"code":637,"filename":62,"language":63,"meta":43,"style":43},"version: \"3\"\n\nservices:\n  dynamodb-local:\n    container_name: dynamodb-local\n    image: amazon\u002Fdynamodb-local\n    ports:\n      - 8000:8000\n    command: -jar DynamoDBLocal.jar -dbPath \u002Fdata -sharedDb\n    volumes:\n      - .\u002Fdata:\u002Fdata\n    networks:\n      - lambda-local\nnetworks:\n  lambda-local:\n    external: true #これ！\n",[41,639,640,652,656,662,668,676,684,690,696,704,710,716,722,728,734,740],{"__ignoreMap":43},[67,641,642,644,646,648,650],{"class":69,"line":70},[67,643,74],{"class":73},[67,645,78],{"class":77},[67,647,81],{"class":77},[67,649,85],{"class":84},[67,651,88],{"class":77},[67,653,654],{"class":69,"line":91},[67,655,95],{"emptyLinePlaceholder":94},[67,657,658,660],{"class":69,"line":98},[67,659,101],{"class":73},[67,661,104],{"class":77},[67,663,664,666],{"class":69,"line":107},[67,665,110],{"class":73},[67,667,104],{"class":77},[67,669,670,672,674],{"class":69,"line":4},[67,671,117],{"class":73},[67,673,78],{"class":77},[67,675,122],{"class":84},[67,677,678,680,682],{"class":69,"line":125},[67,679,128],{"class":73},[67,681,78],{"class":77},[67,683,133],{"class":84},[67,685,686,688],{"class":69,"line":136},[67,687,139],{"class":73},[67,689,104],{"class":77},[67,691,692,694],{"class":69,"line":144},[67,693,147],{"class":77},[67,695,150],{"class":84},[67,697,698,700,702],{"class":69,"line":153},[67,699,156],{"class":73},[67,701,78],{"class":77},[67,703,161],{"class":84},[67,705,706,708],{"class":69,"line":164},[67,707,167],{"class":73},[67,709,104],{"class":77},[67,711,712,714],{"class":69,"line":172},[67,713,147],{"class":77},[67,715,177],{"class":84},[67,717,718,720],{"class":69,"line":180},[67,719,183],{"class":73},[67,721,104],{"class":77},[67,723,724,726],{"class":69,"line":188},[67,725,147],{"class":77},[67,727,193],{"class":84},[67,729,730,732],{"class":69,"line":196},[67,731,199],{"class":73},[67,733,104],{"class":77},[67,735,736,738],{"class":69,"line":204},[67,737,207],{"class":73},[67,739,104],{"class":77},[67,741,742,744,746,749],{"class":69,"line":212},[67,743,215],{"class":73},[67,745,78],{"class":77},[67,747,748],{"class":220}," true",[67,750,752],{"class":751},"sC9rS"," #これ！\n",[13,754,755],{},"そしてSAMコンテナの立ち上げの際、このネットワークに接続できる引数があります。",[34,757,760],{"className":758,"code":759,"language":39},[37],"sam local invoke -e events\u002Fevent.json --docker-network lambda-local\n",[41,761,759],{"__ignoreMap":43},[13,763,764,767],{},[41,765,766],{},"--docker-network lambda-local"," を指定することで、DynamoDBコンテナのネットワークにアクセスできるようになります。そしてホストも以下のように書き換えます。",[34,769,771],{"className":235,"code":770,"filename":237,"language":238,"meta":43,"style":43},"var dynamoOpt = {\n    endpoint: \"http:\u002F\u002Fdynamodb-local:8000\",\n};\n",[41,772,773,783,798],{"__ignoreMap":43},[67,774,775,777,779,781],{"class":69,"line":70},[67,776,291],{"class":245},[67,778,294],{"class":249},[67,780,253],{"class":77},[67,782,299],{"class":77},[67,784,785,787,789,791,794,796],{"class":69,"line":91},[67,786,304],{"class":73},[67,788,78],{"class":77},[67,790,81],{"class":77},[67,792,793],{"class":84},"http:\u002F\u002Fdynamodb-local:8000",[67,795,314],{"class":77},[67,797,317],{"class":77},[67,799,800],{"class":69,"line":98},[67,801,322],{"class":77},[13,803,804],{},"実際のコードではホスト部分は環境変数に置き換えます。とりあえず上記ホストに変更して、もう一度先ほどのコマンドを実行しました。結果、なんとかDynamoDBに接続してCRUD操作ができるようになりました。",[13,806,807],{},"複数のコンテナを立てていたりすると、どこがどう繋がっているか分からなくなるので結構はまりました。汗）",[809,810,811],"style",{},"html pre.shiki code .s-wAU, html code.shiki .s-wAU{--shiki-default:#F07178}html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .sfyAc, html code.shiki .sfyAc{--shiki-default:#C3E88D}html pre.shiki code .sbqyR, html code.shiki .sbqyR{--shiki-default:#FF9CAC}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sJ14y, html code.shiki .sJ14y{--shiki-default:#C792EA}html pre.shiki code .s0W1g, html code.shiki .s0W1g{--shiki-default:#BABED8}html pre.shiki code .sdLwU, html code.shiki .sdLwU{--shiki-default:#82AAFF}html pre.shiki code .s7ZW3, html code.shiki .s7ZW3{--shiki-default:#BABED8;--shiki-default-font-style:italic}html pre.shiki code .s6cf3, html code.shiki .s6cf3{--shiki-default:#89DDFF;--shiki-default-font-style:italic}html pre.shiki code .sx098, html code.shiki .sx098{--shiki-default:#F78C6C}html pre.shiki code .sC9rS, html code.shiki .sC9rS{--shiki-default:#464B5D;--shiki-default-font-style:italic}",{"title":43,"searchDepth":98,"depth":98,"links":813},[814,815],{"id":53,"depth":91,"text":54},{"id":593,"depth":91,"text":593,"children":816},[817,818],{"id":600,"depth":98,"text":601},{"id":630,"depth":98,"text":631},[820],"ministack","2026-05-07","AWS SAMとDynamoDBの接続","md",null,{},"\u002Farticles\u002Faws-sam-disconnect-dymamodb-local",{"title":8,"description":822},"articles\u002Faws-sam-disconnect-dymamodb-local",[830,831,832],"aws","docker","serverless","util\u002Fsam_squirrel.png","wCqQZ02-pnfwd_-TA9YeBhfjRe0nMADGHPc1dk6e2z0",{"id":836,"title":837,"body":838,"category":2650,"createdAt":2652,"description":837,"extension":823,"index":824,"meta":2653,"navigation":94,"path":2654,"publish":94,"seo":2655,"series":824,"seriesTitle":824,"stem":2656,"tag":2657,"thumbnail":2658,"updatedAt":2652,"__hash__":2659},"articles\u002Farticles\u002Fbuild-lamp-with-docker.md","Dockerでosから作るcentos8+apache2.4+laravel 6 開発環境構築",{"type":10,"value":839,"toc":2624},[840,843,846,849,855,858,1108,1111,1124,1127,1130,1140,1154,1157,1160,1163,1166,1415,1418,1422,1491,1503,1511,1529,1532,1536,1542,1560,1578,1585,1588,1594,1600,1604,1637,1655,1663,1666,1699,1702,1706,1709,1726,1729,1732,1738,1752,1758,1761,1767,1988,1991,1994,1997,2096,2107,2111,2114,2152,2168,2171,2205,2223,2227,2334,2343,2346,2349,2356,2362,2372,2378,2390,2394,2408,2414,2421,2424,2428,2438,2444,2451,2457,2462,2467,2470,2476,2483,2489,2492,2496,2499,2505,2508,2514,2525,2531,2540,2546,2556,2566,2572,2580,2612,2615,2618,2621],[13,841,842],{},"こんにちはjunです。laravelの開発環境をDockerで構築した機会がありました。よくlaravelぐらいならば apcheイメージを入れたりして構築すると思います。その場合大体イメージのosがUbuntuになったりしますが、本番環境のosはcentosだったりと「osから構築したいなー」と思ったので今回はDockerfileとdocker-composeを用いてosからlaravelまで構築しようと思います。",[13,844,845],{},"この記事で使用したOSとdockerのバージョン\ndocker：19.03.13\nmaxOS Catalina 10.15.5",[51,847,848],{"id":848},"構成の全体像",[34,850,853],{"className":851,"code":852,"language":39},[37],"centos_laravel\n├── docker-compose.yml\n├── laravel\n│\n├── web\n    ├── Dockerfile\n    ├── httpd.conf\n    └── php.ini\n",[41,854,852],{"__ignoreMap":43},[13,856,857],{},"ディレクトリは上記の様な感じです。docker-compose.ymlは以下の様になっています。",[34,859,863],{"className":860,"code":861,"filename":62,"language":862,"meta":43,"style":43},"language-yml shiki shiki-themes material-theme-ocean","version: '3'\nservices: \n  web_1:\n    image: centos8_apache:1.0\n    depends_on: \n      - db\n    volumes: \n      - .\u002Flaravel\u002F:\u002Fvar\u002Fwww\u002Fhtml\u002F\n      - \u002Fsys\u002Ffs\u002Fcgroup:\u002Fsys\u002Ffs\u002Fcgroup:ro\n    ports: \n      - \"9000:80\"\n      - \"3000:3000\"\n    privileged: true\n    command: \u002Fsbin\u002Finit\n  db:\n    image: mysql:5.7\n    environment:\n      MYSQL_DATABASE: larvel_docker\n      MYSQL_USER: test\n      MYSQL_PASSWORD: testtest\n      MYSQL_ROOT_PASSWORD: rootroot\n    ports: \n      - \"3306:3306\"\n    volumes: \n      - laravel_data:\u002Fvar\u002Flib\u002Fmysql\nvolumes: \n  laravel_data: {}\n","yml",[41,864,865,879,888,895,904,913,920,928,935,942,950,961,972,981,990,997,1006,1013,1023,1033,1043,1053,1061,1072,1080,1087,1097],{"__ignoreMap":43},[67,866,867,869,871,874,876],{"class":69,"line":70},[67,868,74],{"class":73},[67,870,78],{"class":77},[67,872,873],{"class":77}," '",[67,875,85],{"class":84},[67,877,878],{"class":77},"'\n",[67,880,881,883,885],{"class":69,"line":91},[67,882,101],{"class":73},[67,884,78],{"class":77},[67,886,887],{"class":249}," \n",[67,889,890,893],{"class":69,"line":98},[67,891,892],{"class":73},"  web_1",[67,894,104],{"class":77},[67,896,897,899,901],{"class":69,"line":107},[67,898,128],{"class":73},[67,900,78],{"class":77},[67,902,903],{"class":84}," centos8_apache:1.0\n",[67,905,906,909,911],{"class":69,"line":4},[67,907,908],{"class":73},"    depends_on",[67,910,78],{"class":77},[67,912,887],{"class":249},[67,914,915,917],{"class":69,"line":125},[67,916,147],{"class":77},[67,918,919],{"class":84}," db\n",[67,921,922,924,926],{"class":69,"line":136},[67,923,167],{"class":73},[67,925,78],{"class":77},[67,927,887],{"class":249},[67,929,930,932],{"class":69,"line":144},[67,931,147],{"class":77},[67,933,934],{"class":84}," .\u002Flaravel\u002F:\u002Fvar\u002Fwww\u002Fhtml\u002F\n",[67,936,937,939],{"class":69,"line":153},[67,938,147],{"class":77},[67,940,941],{"class":84}," \u002Fsys\u002Ffs\u002Fcgroup:\u002Fsys\u002Ffs\u002Fcgroup:ro\n",[67,943,944,946,948],{"class":69,"line":164},[67,945,139],{"class":73},[67,947,78],{"class":77},[67,949,887],{"class":249},[67,951,952,954,956,959],{"class":69,"line":172},[67,953,147],{"class":77},[67,955,81],{"class":77},[67,957,958],{"class":84},"9000:80",[67,960,88],{"class":77},[67,962,963,965,967,970],{"class":69,"line":180},[67,964,147],{"class":77},[67,966,81],{"class":77},[67,968,969],{"class":84},"3000:3000",[67,971,88],{"class":77},[67,973,974,977,979],{"class":69,"line":188},[67,975,976],{"class":73},"    privileged",[67,978,78],{"class":77},[67,980,221],{"class":220},[67,982,983,985,987],{"class":69,"line":196},[67,984,156],{"class":73},[67,986,78],{"class":77},[67,988,989],{"class":84}," \u002Fsbin\u002Finit\n",[67,991,992,995],{"class":69,"line":204},[67,993,994],{"class":73},"  db",[67,996,104],{"class":77},[67,998,999,1001,1003],{"class":69,"line":212},[67,1000,128],{"class":73},[67,1002,78],{"class":77},[67,1004,1005],{"class":84}," mysql:5.7\n",[67,1007,1008,1011],{"class":69,"line":467},[67,1009,1010],{"class":73},"    environment",[67,1012,104],{"class":77},[67,1014,1015,1018,1020],{"class":69,"line":497},[67,1016,1017],{"class":73},"      MYSQL_DATABASE",[67,1019,78],{"class":77},[67,1021,1022],{"class":84}," larvel_docker\n",[67,1024,1025,1028,1030],{"class":69,"line":503},[67,1026,1027],{"class":73},"      MYSQL_USER",[67,1029,78],{"class":77},[67,1031,1032],{"class":84}," test\n",[67,1034,1035,1038,1040],{"class":69,"line":521},[67,1036,1037],{"class":73},"      MYSQL_PASSWORD",[67,1039,78],{"class":77},[67,1041,1042],{"class":84}," testtest\n",[67,1044,1045,1048,1050],{"class":69,"line":528},[67,1046,1047],{"class":73},"      MYSQL_ROOT_PASSWORD",[67,1049,78],{"class":77},[67,1051,1052],{"class":84}," rootroot\n",[67,1054,1055,1057,1059],{"class":69,"line":540},[67,1056,139],{"class":73},[67,1058,78],{"class":77},[67,1060,887],{"class":249},[67,1062,1063,1065,1067,1070],{"class":69,"line":557},[67,1064,147],{"class":77},[67,1066,81],{"class":77},[67,1068,1069],{"class":84},"3306:3306",[67,1071,88],{"class":77},[67,1073,1074,1076,1078],{"class":69,"line":562},[67,1075,167],{"class":73},[67,1077,78],{"class":77},[67,1079,887],{"class":249},[67,1081,1082,1084],{"class":69,"line":568},[67,1083,147],{"class":77},[67,1085,1086],{"class":84}," laravel_data:\u002Fvar\u002Flib\u002Fmysql\n",[67,1088,1090,1093,1095],{"class":69,"line":1089},26,[67,1091,1092],{"class":73},"volumes",[67,1094,78],{"class":77},[67,1096,887],{"class":249},[67,1098,1100,1103,1105],{"class":69,"line":1099},27,[67,1101,1102],{"class":73},"  laravel_data",[67,1104,78],{"class":77},[67,1106,1107],{"class":77}," {}\n",[13,1109,1110],{},"構築の流れとしては",[1112,1113,1114,1118,1121],"ul",{},[1115,1116,1117],"li",{},"centos8、apache2.4、php7.4、nodejsが入ったwebサーバーイメージを作成",[1115,1119,1120],{},"webサーバーイメージとmysqlイメージで作られた2つのコンテナをdocker-composeで連携する",[1115,1122,1123],{},"laraevelのマイグレーションを行う。",[13,1125,1126],{},"と行った流れで行います。",[598,1128,1129],{"id":1129},"webサーバーイメージ",[13,1131,1132,1135,1136,1139],{},[41,1133,1134],{},"web","ディレクトリ配下にはcentos8、apache、php、nodeがインストールされたイメージを作成する",[41,1137,1138],{},"Dockerfile","とapacheの設定ファイル、phpの設定ファイルがあります。",[13,1141,1142,1143,1146,1147,1149,1150,1153],{},"laravelでは実運用の際にドキュメントルート を変更する必要があるので",[41,1144,1145],{},"httpd.conf","を編集して、それをコンテナの",[41,1148,1145],{},"にコピーしています。",[41,1151,1152],{},"php.ini","はタイムゾーン を書き足すぐらいですけど同じ様にエディタ上で設定ファイルを変更できる様にしています。",[598,1155,1156],{"id":1156},"laravelディレクトリ",[13,1158,1159],{},"larvelディレクトリはlaravelソースが予めインストールされています。そのソースをコンテナのドキュメントルート 配下にボリュームすることでローカルのエディタで編集してコンテナ環境でレビューすることができます。",[51,1161,1162],{"id":1162},"webサーバーイメージを作成",[13,1164,1165],{},"それではまずwebサーバーイメージを作成していきます。と言っても以下のDockerfileの内容で事足ります。",[34,1167,1171],{"className":1168,"code":1169,"language":1170,"meta":43,"style":43},"language-dockerfile shiki shiki-themes material-theme-ocean","FROM centos:8\n\nENV container docker\nRUN (cd \u002Flib\u002Fsystemd\u002Fsystem\u002Fsysinit.target.wants\u002F; for i in *; do [ $i == \\\nsystemd-tmpfiles-setup.service ] || rm -f $i; done); \\\nrm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Fmulti-user.target.wants\u002F*;\\\nrm -f \u002Fetc\u002Fsystemd\u002Fsystem\u002F*.wants\u002F*;\\\nrm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Flocal-fs.target.wants\u002F*; \\\nrm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Fsockets.target.wants\u002F*udev*; \\\nrm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Fsockets.target.wants\u002F*initctl*; \\\nrm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Fbasic.target.wants\u002F*;\\\nrm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Fanaconda.target.wants\u002F*;\nVOLUME [ \"\u002Fsys\u002Ffs\u002Fcgroup\" ]\nCMD [\"\u002Fusr\u002Fsbin\u002Finit\"]\n\nRUN \u002Fbin\u002Fcp \u002Fusr\u002Fshare\u002Fzoneinfo\u002FAsia\u002FTokyo \u002Fetc\u002Flocaltime\n\nRUN yum install -y epel-release && yum clean all\n\nRUN rpm -ivh http:\u002F\u002Fftp.riken.jp\u002FLinux\u002Fremi\u002Fenterprise\u002Fremi-release-8.rpm\n\nRUN yum -y update && yum clean all\n\nRUN yum -y install httpd && yum clean all\n\nCOPY .\u002Fhttpd.conf \u002Fetc\u002Fhttpd\u002Fconf\u002Fhttpd.conf\n\nRUN yum -y install php74-php php74-php-mysqli php74-php-gd php74-php-mbstring php74-php-opcache php74-php-xml php74-php-pear php74-php-devel php74-php-pecl-imagick php74-php-pecl-imagick-devel php74-php-pecl-zip\n\nRUN ln \u002Fusr\u002Fbin\u002Fphp74 \u002Fusr\u002Fbin\u002Fphp\n\nCOPY .\u002Fphp.ini \u002Fetc\u002Fopt\u002Fremi\u002Fphp74\u002Fphp.ini\n\nRUN chown -R apache:apache \u002Fvar\u002Fwww\u002Fhtml\n\nRUN systemctl enable php74-php-fpm\n\nRUN systemctl enable httpd \n\nVOLUME [ \"\u002Fvar\u002Fwww\u002Fhtml\" ]\n\nRUN chown -R apache:apache \u002Fvar\u002Fwww\u002Fhtml\n\nRUN dnf -y module enable nodejs:12\n\nRUN dnf -y install nodejs\n\nEXPOSE 80\n","dockerfile",[41,1172,1173,1178,1182,1187,1192,1197,1202,1207,1212,1217,1222,1227,1232,1237,1242,1246,1251,1255,1260,1264,1269,1273,1278,1282,1287,1291,1296,1300,1306,1311,1317,1322,1328,1333,1339,1344,1350,1355,1361,1366,1372,1377,1382,1387,1393,1398,1404,1409],{"__ignoreMap":43},[67,1174,1175],{"class":69,"line":70},[67,1176,1177],{},"FROM centos:8\n",[67,1179,1180],{"class":69,"line":91},[67,1181,95],{"emptyLinePlaceholder":94},[67,1183,1184],{"class":69,"line":98},[67,1185,1186],{},"ENV container docker\n",[67,1188,1189],{"class":69,"line":107},[67,1190,1191],{},"RUN (cd \u002Flib\u002Fsystemd\u002Fsystem\u002Fsysinit.target.wants\u002F; for i in *; do [ $i == \\\n",[67,1193,1194],{"class":69,"line":4},[67,1195,1196],{},"systemd-tmpfiles-setup.service ] || rm -f $i; done); \\\n",[67,1198,1199],{"class":69,"line":125},[67,1200,1201],{},"rm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Fmulti-user.target.wants\u002F*;\\\n",[67,1203,1204],{"class":69,"line":136},[67,1205,1206],{},"rm -f \u002Fetc\u002Fsystemd\u002Fsystem\u002F*.wants\u002F*;\\\n",[67,1208,1209],{"class":69,"line":144},[67,1210,1211],{},"rm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Flocal-fs.target.wants\u002F*; \\\n",[67,1213,1214],{"class":69,"line":153},[67,1215,1216],{},"rm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Fsockets.target.wants\u002F*udev*; \\\n",[67,1218,1219],{"class":69,"line":164},[67,1220,1221],{},"rm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Fsockets.target.wants\u002F*initctl*; \\\n",[67,1223,1224],{"class":69,"line":172},[67,1225,1226],{},"rm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Fbasic.target.wants\u002F*;\\\n",[67,1228,1229],{"class":69,"line":180},[67,1230,1231],{},"rm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Fanaconda.target.wants\u002F*;\n",[67,1233,1234],{"class":69,"line":188},[67,1235,1236],{},"VOLUME [ \"\u002Fsys\u002Ffs\u002Fcgroup\" ]\n",[67,1238,1239],{"class":69,"line":196},[67,1240,1241],{},"CMD [\"\u002Fusr\u002Fsbin\u002Finit\"]\n",[67,1243,1244],{"class":69,"line":204},[67,1245,95],{"emptyLinePlaceholder":94},[67,1247,1248],{"class":69,"line":212},[67,1249,1250],{},"RUN \u002Fbin\u002Fcp \u002Fusr\u002Fshare\u002Fzoneinfo\u002FAsia\u002FTokyo \u002Fetc\u002Flocaltime\n",[67,1252,1253],{"class":69,"line":467},[67,1254,95],{"emptyLinePlaceholder":94},[67,1256,1257],{"class":69,"line":497},[67,1258,1259],{},"RUN yum install -y epel-release && yum clean all\n",[67,1261,1262],{"class":69,"line":503},[67,1263,95],{"emptyLinePlaceholder":94},[67,1265,1266],{"class":69,"line":521},[67,1267,1268],{},"RUN rpm -ivh http:\u002F\u002Fftp.riken.jp\u002FLinux\u002Fremi\u002Fenterprise\u002Fremi-release-8.rpm\n",[67,1270,1271],{"class":69,"line":528},[67,1272,95],{"emptyLinePlaceholder":94},[67,1274,1275],{"class":69,"line":540},[67,1276,1277],{},"RUN yum -y update && yum clean all\n",[67,1279,1280],{"class":69,"line":557},[67,1281,95],{"emptyLinePlaceholder":94},[67,1283,1284],{"class":69,"line":562},[67,1285,1286],{},"RUN yum -y install httpd && yum clean all\n",[67,1288,1289],{"class":69,"line":568},[67,1290,95],{"emptyLinePlaceholder":94},[67,1292,1293],{"class":69,"line":1089},[67,1294,1295],{},"COPY .\u002Fhttpd.conf \u002Fetc\u002Fhttpd\u002Fconf\u002Fhttpd.conf\n",[67,1297,1298],{"class":69,"line":1099},[67,1299,95],{"emptyLinePlaceholder":94},[67,1301,1303],{"class":69,"line":1302},28,[67,1304,1305],{},"RUN yum -y install php74-php php74-php-mysqli php74-php-gd php74-php-mbstring php74-php-opcache php74-php-xml php74-php-pear php74-php-devel php74-php-pecl-imagick php74-php-pecl-imagick-devel php74-php-pecl-zip\n",[67,1307,1309],{"class":69,"line":1308},29,[67,1310,95],{"emptyLinePlaceholder":94},[67,1312,1314],{"class":69,"line":1313},30,[67,1315,1316],{},"RUN ln \u002Fusr\u002Fbin\u002Fphp74 \u002Fusr\u002Fbin\u002Fphp\n",[67,1318,1320],{"class":69,"line":1319},31,[67,1321,95],{"emptyLinePlaceholder":94},[67,1323,1325],{"class":69,"line":1324},32,[67,1326,1327],{},"COPY .\u002Fphp.ini \u002Fetc\u002Fopt\u002Fremi\u002Fphp74\u002Fphp.ini\n",[67,1329,1331],{"class":69,"line":1330},33,[67,1332,95],{"emptyLinePlaceholder":94},[67,1334,1336],{"class":69,"line":1335},34,[67,1337,1338],{},"RUN chown -R apache:apache \u002Fvar\u002Fwww\u002Fhtml\n",[67,1340,1342],{"class":69,"line":1341},35,[67,1343,95],{"emptyLinePlaceholder":94},[67,1345,1347],{"class":69,"line":1346},36,[67,1348,1349],{},"RUN systemctl enable php74-php-fpm\n",[67,1351,1353],{"class":69,"line":1352},37,[67,1354,95],{"emptyLinePlaceholder":94},[67,1356,1358],{"class":69,"line":1357},38,[67,1359,1360],{},"RUN systemctl enable httpd \n",[67,1362,1364],{"class":69,"line":1363},39,[67,1365,95],{"emptyLinePlaceholder":94},[67,1367,1369],{"class":69,"line":1368},40,[67,1370,1371],{},"VOLUME [ \"\u002Fvar\u002Fwww\u002Fhtml\" ]\n",[67,1373,1375],{"class":69,"line":1374},41,[67,1376,95],{"emptyLinePlaceholder":94},[67,1378,1380],{"class":69,"line":1379},42,[67,1381,1338],{},[67,1383,1385],{"class":69,"line":1384},43,[67,1386,95],{"emptyLinePlaceholder":94},[67,1388,1390],{"class":69,"line":1389},44,[67,1391,1392],{},"RUN dnf -y module enable nodejs:12\n",[67,1394,1396],{"class":69,"line":1395},45,[67,1397,95],{"emptyLinePlaceholder":94},[67,1399,1401],{"class":69,"line":1400},46,[67,1402,1403],{},"RUN dnf -y install nodejs\n",[67,1405,1407],{"class":69,"line":1406},47,[67,1408,95],{"emptyLinePlaceholder":94},[67,1410,1412],{"class":69,"line":1411},48,[67,1413,1414],{},"EXPOSE 80\n",[13,1416,1417],{},"もう少し細かく解説していきます。",[598,1419,1421],{"id":1420},"centos8をいれ設定","centos8をいれ、設定",[34,1423,1425],{"className":1168,"code":1424,"language":1170,"meta":43,"style":43},"FROM centos:8\n\nENV container docker\nRUN (cd \u002Flib\u002Fsystemd\u002Fsystem\u002Fsysinit.target.wants\u002F; for i in *; do [ $i == \\\nsystemd-tmpfiles-setup.service ] || rm -f $i; done); \\\nrm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Fmulti-user.target.wants\u002F*;\\\nrm -f \u002Fetc\u002Fsystemd\u002Fsystem\u002F*.wants\u002F*;\\\nrm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Flocal-fs.target.wants\u002F*; \\\nrm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Fsockets.target.wants\u002F*udev*; \\\nrm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Fsockets.target.wants\u002F*initctl*; \\\nrm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Fbasic.target.wants\u002F*;\\\nrm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Fanaconda.target.wants\u002F*;\nVOLUME [ \"\u002Fsys\u002Ffs\u002Fcgroup\" ]\nCMD [\"\u002Fusr\u002Fsbin\u002Finit\"]\n\nRUN \u002Fbin\u002Fcp \u002Fusr\u002Fshare\u002Fzoneinfo\u002FAsia\u002FTokyo \u002Fetc\u002Flocaltime\n",[41,1426,1427,1431,1435,1439,1443,1447,1451,1455,1459,1463,1467,1471,1475,1479,1483,1487],{"__ignoreMap":43},[67,1428,1429],{"class":69,"line":70},[67,1430,1177],{},[67,1432,1433],{"class":69,"line":91},[67,1434,95],{"emptyLinePlaceholder":94},[67,1436,1437],{"class":69,"line":98},[67,1438,1186],{},[67,1440,1441],{"class":69,"line":107},[67,1442,1191],{},[67,1444,1445],{"class":69,"line":4},[67,1446,1196],{},[67,1448,1449],{"class":69,"line":125},[67,1450,1201],{},[67,1452,1453],{"class":69,"line":136},[67,1454,1206],{},[67,1456,1457],{"class":69,"line":144},[67,1458,1211],{},[67,1460,1461],{"class":69,"line":153},[67,1462,1216],{},[67,1464,1465],{"class":69,"line":164},[67,1466,1221],{},[67,1468,1469],{"class":69,"line":172},[67,1470,1226],{},[67,1472,1473],{"class":69,"line":180},[67,1474,1231],{},[67,1476,1477],{"class":69,"line":188},[67,1478,1236],{},[67,1480,1481],{"class":69,"line":196},[67,1482,1241],{},[67,1484,1485],{"class":69,"line":204},[67,1486,95],{"emptyLinePlaceholder":94},[67,1488,1489],{"class":69,"line":212},[67,1490,1250],{},[13,1492,1493,1496,1497,1502],{},[41,1494,1495],{},"FROM centos:8","で書かれている様に、centos8自身のイメージは公式の",[23,1498,1501],{"href":1499,"rel":1500},"https:\u002F\u002Fhub.docker.com\u002F_\u002Fcentos",[27],"dockerHub","からpullします。そしてこれらの記述は公式の手順のソースを貼り付けた感じです。",[13,1504,1505,1506,1510],{},"以前dockerにcentos8の環境を作ろうとして詰まった時がありました（",[23,1507,1509],{"href":1508},"\u002Farticles\u002Fstuck-on-docker-centos8","こちら","の記事）。その際はこの以下の部分だけを書いていました。",[34,1512,1514],{"className":1168,"code":1513,"language":1170,"meta":43,"style":43},"FROM centos:8\nRUN \u002Fbin\u002Fcp \u002Fusr\u002Fshare\u002Fzoneinfo\u002FAsia\u002FTokyo \u002Fetc\u002Flocaltime\n#..以下同じ\n",[41,1515,1516,1520,1524],{"__ignoreMap":43},[67,1517,1518],{"class":69,"line":70},[67,1519,1177],{},[67,1521,1522],{"class":69,"line":91},[67,1523,1250],{},[67,1525,1526],{"class":69,"line":98},[67,1527,1528],{},"#..以下同じ\n",[13,1530,1531],{},"純粋に公式のcentosイメージはデフォルトでsystemdがアクティブにならず、コンテナを立てても応答しません。docker-composeの際にも一工夫必要になりますが、まずは上の方の記述でcenotsのイメージ設定をしましょう。",[598,1533,1535],{"id":1534},"apache24をいれる","apache2.4をいれる",[34,1537,1540],{"className":1538,"code":1539,"language":39},[37],"RUN yum -y install httpd && yum clean all\n\nCOPY .\u002Fhttpd.conf \u002Fetc\u002Fhttpd\u002Fconf\u002Fhttpd.conf\n",[41,1541,1539],{"__ignoreMap":43},[13,1543,1544,1545,1548,1549,1552,1553,1556,1557,1559],{},"こんだけです。",[41,1546,1547],{},"yum -y install httpd","を",[41,1550,1551],{},"RUN","してhttpdを入れているだけですね。ちなみにdockerコンテナ内でyumなどを用いてインストールする際は",[41,1554,1555],{},"-y","オプションをつけましょう。",[41,1558,1555],{},"オプションは全てyesで答えるというオプションです。これがないとインストール時に「本当にインストールしますか？（Yes\u002FNo）」と聞かれ、ビルドがとまります。",[13,1561,1562,1563,1565,1566,1568,1569,1571,1572,1574,1575,1577],{},"そして",[41,1564,1138],{},"と同じディレクトリにいる",[41,1567,1145],{},"をコンテナ内の",[41,1570,1145],{},"にCOPYします。",[41,1573,1145],{},"は別途にapache2.4コンテナを立ててコピーするか、最初はこのCOPY部分をコメントアウトして一度この",[41,1576,1138],{},"をビルドしてコピーしても大丈夫です。",[1579,1580,1584],"div",{"className":1581},[1582,1583],"alert","alert-info","\nコンテナ内からソースを手元にコピーするためにはdocker cp コマンドを用います。\n",[13,1586,1587],{},"例えば別途にapache2.4という名前でコンテナを立ち上げている場合、以下の様にしてhttpd.confをコピーします。",[34,1589,1592],{"className":1590,"code":1591,"language":39},[37],"docker container cp apache2.4:\u002Fetc\u002Fhttpd\u002Fconf\u002Fhttpd.conf .\u002F\n",[41,1593,1591],{"__ignoreMap":43},[13,1595,1596,1597,1599],{},"こうするとコンテナ内のソースが手元にコピーされます。インストールする環境によって",[41,1598,1145],{},"の置き場所が変わったりもするのでまずはCOPY無しでビルドして、パスを確認してから手元にコピーするといいです。",[598,1601,1603],{"id":1602},"php-をいれる","php をいれる",[34,1605,1607],{"className":1168,"code":1606,"language":1170,"meta":43,"style":43},"RUN rpm -ivh http:\u002F\u002Fftp.riken.jp\u002FLinux\u002Fremi\u002Fenterprise\u002Fremi-release-8.rpm\n\nRUN yum -y install php74-php php74-php-mysqli php74-php-gd php74-php-mbstring php74-php-opcache php74-php-xml php74-php-pear php74-php-devel php74-php-pecl-imagick php74-php-pecl-imagick-devel php74-php-pecl-zip\n\nRUN ln \u002Fusr\u002Fbin\u002Fphp74 \u002Fusr\u002Fbin\u002Fphp\n\nCOPY .\u002Fphp.ini \u002Fetc\u002Fopt\u002Fremi\u002Fphp74\u002Fphp.ini\n",[41,1608,1609,1613,1617,1621,1625,1629,1633],{"__ignoreMap":43},[67,1610,1611],{"class":69,"line":70},[67,1612,1268],{},[67,1614,1615],{"class":69,"line":91},[67,1616,95],{"emptyLinePlaceholder":94},[67,1618,1619],{"class":69,"line":98},[67,1620,1305],{},[67,1622,1623],{"class":69,"line":107},[67,1624,95],{"emptyLinePlaceholder":94},[67,1626,1627],{"class":69,"line":4},[67,1628,1316],{},[67,1630,1631],{"class":69,"line":125},[67,1632,95],{"emptyLinePlaceholder":94},[67,1634,1635],{"class":69,"line":136},[67,1636,1327],{},[13,1638,1639,1642,1643,1646,1647,1650,1651,1654],{},[41,1640,1641],{},"remi","リポジトリをインストールして",[41,1644,1645],{},"yum","を通じてphp7.4を入れます。",[41,1648,1649],{},"RUN ln \u002Fusr\u002Fbin\u002Fphp74 \u002Fusr\u002Fbin\u002Fphp"," で ",[41,1652,1653],{},"php","コマンドを使用できる様にします。",[13,1656,1562,1657,1659,1660,1662],{},[41,1658,1145],{},"と同じ様に",[41,1661,1152],{},"を手元からコピーします。",[598,1664,1665],{"id":1665},"権限の設定と永続化",[34,1667,1669],{"className":1168,"code":1668,"language":1170,"meta":43,"style":43},"RUN chown -R apache:apache \u002Fvar\u002Fwww\u002Fhtml\n\nRUN systemctl enable php74-php-fpm\n\nRUN systemctl enable httpd \n\nVOLUME [ \"\u002Fvar\u002Fwww\u002Fhtml\" ]\n",[41,1670,1671,1675,1679,1683,1687,1691,1695],{"__ignoreMap":43},[67,1672,1673],{"class":69,"line":70},[67,1674,1338],{},[67,1676,1677],{"class":69,"line":91},[67,1678,95],{"emptyLinePlaceholder":94},[67,1680,1681],{"class":69,"line":98},[67,1682,1349],{},[67,1684,1685],{"class":69,"line":107},[67,1686,95],{"emptyLinePlaceholder":94},[67,1688,1689],{"class":69,"line":4},[67,1690,1360],{},[67,1692,1693],{"class":69,"line":125},[67,1694,95],{"emptyLinePlaceholder":94},[67,1696,1697],{"class":69,"line":136},[67,1698,1371],{},[13,1700,1701],{},"webサーバーとphpを入れたのでドキュメントルート をapacheが触れる様に権限を変更します。そしてwebサーバーとphp-fpmが自動で起動する様にします。最後にlaravelプロジェクトをドキュメントルート配下にボリュームできる様にボリュームの設定をします。",[598,1703,1705],{"id":1704},"nodejsをいれるおまけ","node.jsをいれる（おまけ）",[13,1707,1708],{},"node.jsをいれるのはフロントの開発でnuxt.jsを用いるためです。ここは飛ばしても構いません。",[34,1710,1712],{"className":1168,"code":1711,"language":1170,"meta":43,"style":43},"RUN dnf -y module enable nodejs:12\n\nRUN dnf -y install nodejs\n",[41,1713,1714,1718,1722],{"__ignoreMap":43},[67,1715,1716],{"class":69,"line":70},[67,1717,1392],{},[67,1719,1720],{"class":69,"line":91},[67,1721,95],{"emptyLinePlaceholder":94},[67,1723,1724],{"class":69,"line":98},[67,1725,1403],{},[51,1727,1728],{"id":1728},"イメージをビルドする",[13,1730,1731],{},"webサーバーのDockerfileが書き終わったのでまずビルドしてイメージを作りましょう。Dockerfileがあるディレクトリで以下のコマンドを唱えます。",[34,1733,1736],{"className":1734,"code":1735,"language":39},[37],"$ docker build -t centos_apache:1.0 . \n",[41,1737,1735],{"__ignoreMap":43},[13,1739,1740,1743,1744,1747,1748,1751],{},[41,1741,1742],{},". ","は「現在のディレクトリ」という意味です。そして -t でタグをつけを有効にします。今回作成したイメージは ",[41,1745,1746],{},"centos_apache","で",[41,1749,1750],{},"1.0","というタグをつけておきます。ビルドは少し時間がかかりますが、完了すればローカルにこのイメージが登録されます。dockerhubなどに置いておけば、他の人にがpullできる様になります。",[34,1753,1756],{"className":1754,"code":1755,"language":39},[37],"$ docker images                                           \nREPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE\ncentos_apache                   1.0                54784hkjdfjk        17 hours ago        941MB\n",[41,1757,1755],{"__ignoreMap":43},[51,1759,1760],{"id":1760},"docker-composeを作成",[13,1762,1763,1764,1766],{},"それではosから調整したwebサーバーイメージは作成できたので、次はdocker-composeを使用してDBコンテナとの連携などをしていきます。",[41,1765,62],{},"は以下の通りです。",[34,1768,1770],{"className":860,"code":1769,"filename":62,"language":862,"meta":43,"style":43},"version: '3'\nservices: \n  web_1:\n    image: centos_apache:1.0\n    depends_on: \n      - db\n    volumes: \n      - .\u002Flaravel\u002F:\u002Fvar\u002Fwww\u002Fhtml\u002F\n      - \u002Fsys\u002Ffs\u002Fcgroup:\u002Fsys\u002Ffs\u002Fcgroup:ro\n    ports: \n      - \"9000:80\"\n      - \"3000:3000\"\n    privileged: true\n    command: \u002Fsbin\u002Finit\n  db:\n    image: mysql:5.7\n    environment:\n      MYSQL_DATABASE: trend_system\n      MYSQL_USER: trend\n      MYSQL_PASSWORD: trendtrend\n      MYSQL_ROOT_PASSWORD: rootroot\n    ports: \n      - \"3306:3306\"\n    volumes: \n      - laravel_data:\u002Fvar\u002Flib\u002Fmysql\nvolumes: \n  laravel_data: {}\n",[41,1771,1772,1784,1792,1798,1807,1815,1821,1829,1835,1841,1849,1859,1869,1877,1885,1891,1899,1905,1914,1923,1932,1940,1948,1958,1966,1972,1980],{"__ignoreMap":43},[67,1773,1774,1776,1778,1780,1782],{"class":69,"line":70},[67,1775,74],{"class":73},[67,1777,78],{"class":77},[67,1779,873],{"class":77},[67,1781,85],{"class":84},[67,1783,878],{"class":77},[67,1785,1786,1788,1790],{"class":69,"line":91},[67,1787,101],{"class":73},[67,1789,78],{"class":77},[67,1791,887],{"class":249},[67,1793,1794,1796],{"class":69,"line":98},[67,1795,892],{"class":73},[67,1797,104],{"class":77},[67,1799,1800,1802,1804],{"class":69,"line":107},[67,1801,128],{"class":73},[67,1803,78],{"class":77},[67,1805,1806],{"class":84}," centos_apache:1.0\n",[67,1808,1809,1811,1813],{"class":69,"line":4},[67,1810,908],{"class":73},[67,1812,78],{"class":77},[67,1814,887],{"class":249},[67,1816,1817,1819],{"class":69,"line":125},[67,1818,147],{"class":77},[67,1820,919],{"class":84},[67,1822,1823,1825,1827],{"class":69,"line":136},[67,1824,167],{"class":73},[67,1826,78],{"class":77},[67,1828,887],{"class":249},[67,1830,1831,1833],{"class":69,"line":144},[67,1832,147],{"class":77},[67,1834,934],{"class":84},[67,1836,1837,1839],{"class":69,"line":153},[67,1838,147],{"class":77},[67,1840,941],{"class":84},[67,1842,1843,1845,1847],{"class":69,"line":164},[67,1844,139],{"class":73},[67,1846,78],{"class":77},[67,1848,887],{"class":249},[67,1850,1851,1853,1855,1857],{"class":69,"line":172},[67,1852,147],{"class":77},[67,1854,81],{"class":77},[67,1856,958],{"class":84},[67,1858,88],{"class":77},[67,1860,1861,1863,1865,1867],{"class":69,"line":180},[67,1862,147],{"class":77},[67,1864,81],{"class":77},[67,1866,969],{"class":84},[67,1868,88],{"class":77},[67,1870,1871,1873,1875],{"class":69,"line":188},[67,1872,976],{"class":73},[67,1874,78],{"class":77},[67,1876,221],{"class":220},[67,1878,1879,1881,1883],{"class":69,"line":196},[67,1880,156],{"class":73},[67,1882,78],{"class":77},[67,1884,989],{"class":84},[67,1886,1887,1889],{"class":69,"line":204},[67,1888,994],{"class":73},[67,1890,104],{"class":77},[67,1892,1893,1895,1897],{"class":69,"line":212},[67,1894,128],{"class":73},[67,1896,78],{"class":77},[67,1898,1005],{"class":84},[67,1900,1901,1903],{"class":69,"line":467},[67,1902,1010],{"class":73},[67,1904,104],{"class":77},[67,1906,1907,1909,1911],{"class":69,"line":497},[67,1908,1017],{"class":73},[67,1910,78],{"class":77},[67,1912,1913],{"class":84}," trend_system\n",[67,1915,1916,1918,1920],{"class":69,"line":503},[67,1917,1027],{"class":73},[67,1919,78],{"class":77},[67,1921,1922],{"class":84}," trend\n",[67,1924,1925,1927,1929],{"class":69,"line":521},[67,1926,1037],{"class":73},[67,1928,78],{"class":77},[67,1930,1931],{"class":84}," trendtrend\n",[67,1933,1934,1936,1938],{"class":69,"line":528},[67,1935,1047],{"class":73},[67,1937,78],{"class":77},[67,1939,1052],{"class":84},[67,1941,1942,1944,1946],{"class":69,"line":540},[67,1943,139],{"class":73},[67,1945,78],{"class":77},[67,1947,887],{"class":249},[67,1949,1950,1952,1954,1956],{"class":69,"line":557},[67,1951,147],{"class":77},[67,1953,81],{"class":77},[67,1955,1069],{"class":84},[67,1957,88],{"class":77},[67,1959,1960,1962,1964],{"class":69,"line":562},[67,1961,167],{"class":73},[67,1963,78],{"class":77},[67,1965,887],{"class":249},[67,1967,1968,1970],{"class":69,"line":568},[67,1969,147],{"class":77},[67,1971,1086],{"class":84},[67,1973,1974,1976,1978],{"class":69,"line":1089},[67,1975,1092],{"class":73},[67,1977,78],{"class":77},[67,1979,887],{"class":249},[67,1981,1982,1984,1986],{"class":69,"line":1099},[67,1983,1102],{"class":73},[67,1985,78],{"class":77},[67,1987,1107],{"class":77},[13,1989,1990],{},"コンテナはwebサーバーとDBサーバーの二つをたて、それらをdepends_onを通じて連携します。そして手元にはlaravelとnuxtをインストールしたプロジェクトディレクトリを置いておき、それをコンテナのドキュメントルートに置くと行った手順です。",[13,1992,1993],{},"それでは詳細を解説していきます。",[598,1995,1996],{"id":1996},"webサーバーコンテナの記述",[34,1998,2000],{"className":860,"code":1999,"filename":62,"language":862,"meta":43,"style":43},"web_1:\n    image: centos_apache:1.0\n    depends_on: \n        - db\n    volumes: \n        - .\u002Flaravel\u002F:\u002Fvar\u002Fwww\u002Fhtml\u002F\n        - \u002Fsys\u002Ffs\u002Fcgroup:\u002Fsys\u002Ffs\u002Fcgroup:ro\n    ports: \n        - \"9000:80\"\n        - \"3000:3000\"\n    privileged: true\n    command: \u002Fsbin\u002Finit\n",[41,2001,2002,2009,2017,2025,2032,2040,2046,2052,2060,2070,2080,2088],{"__ignoreMap":43},[67,2003,2004,2007],{"class":69,"line":70},[67,2005,2006],{"class":73},"web_1",[67,2008,104],{"class":77},[67,2010,2011,2013,2015],{"class":69,"line":91},[67,2012,128],{"class":73},[67,2014,78],{"class":77},[67,2016,1806],{"class":84},[67,2018,2019,2021,2023],{"class":69,"line":98},[67,2020,908],{"class":73},[67,2022,78],{"class":77},[67,2024,887],{"class":249},[67,2026,2027,2030],{"class":69,"line":107},[67,2028,2029],{"class":77},"        -",[67,2031,919],{"class":84},[67,2033,2034,2036,2038],{"class":69,"line":4},[67,2035,167],{"class":73},[67,2037,78],{"class":77},[67,2039,887],{"class":249},[67,2041,2042,2044],{"class":69,"line":125},[67,2043,2029],{"class":77},[67,2045,934],{"class":84},[67,2047,2048,2050],{"class":69,"line":136},[67,2049,2029],{"class":77},[67,2051,941],{"class":84},[67,2053,2054,2056,2058],{"class":69,"line":144},[67,2055,139],{"class":73},[67,2057,78],{"class":77},[67,2059,887],{"class":249},[67,2061,2062,2064,2066,2068],{"class":69,"line":153},[67,2063,2029],{"class":77},[67,2065,81],{"class":77},[67,2067,958],{"class":84},[67,2069,88],{"class":77},[67,2071,2072,2074,2076,2078],{"class":69,"line":164},[67,2073,2029],{"class":77},[67,2075,81],{"class":77},[67,2077,969],{"class":84},[67,2079,88],{"class":77},[67,2081,2082,2084,2086],{"class":69,"line":172},[67,2083,976],{"class":73},[67,2085,78],{"class":77},[67,2087,221],{"class":220},[67,2089,2090,2092,2094],{"class":69,"line":180},[67,2091,156],{"class":73},[67,2093,78],{"class":77},[67,2095,989],{"class":84},[13,2097,2098,2099,2102,2103,2106],{},"この箇所は先ほどビルドしたwebサーバーイメージを用いたコンテナに関する記述です。",[41,2100,2101],{},"depends_on: -db","とすることでDBと連携ができる様になります。そして",[41,2104,2105],{},".\u002Flaravel\u002F:\u002Fvar\u002Fwww\u002Fhtml\u002F","でプロジェクトソースをコンテナに入れ込んでいます。",[2108,2109,2110],"h4",{"id":2110},"centosのための記述",[13,2112,2113],{},"そして先述の通りcenots8のイメージを使用している場合はコンテナがきちんと起動するために以下のコードが必要です。",[34,2115,2117],{"className":860,"code":2116,"filename":62,"language":862,"meta":43,"style":43},"volumes: \n    - \u002Fsys\u002Ffs\u002Fcgroup:\u002Fsys\u002Ffs\u002Fcgroup:ro\nprivileged: true\ncommand: \u002Fsbin\u002Finit\n",[41,2118,2119,2127,2134,2143],{"__ignoreMap":43},[67,2120,2121,2123,2125],{"class":69,"line":70},[67,2122,1092],{"class":73},[67,2124,78],{"class":77},[67,2126,887],{"class":249},[67,2128,2129,2132],{"class":69,"line":91},[67,2130,2131],{"class":77},"    -",[67,2133,941],{"class":84},[67,2135,2136,2139,2141],{"class":69,"line":98},[67,2137,2138],{"class":73},"privileged",[67,2140,78],{"class":77},[67,2142,221],{"class":220},[67,2144,2145,2148,2150],{"class":69,"line":107},[67,2146,2147],{"class":73},"command",[67,2149,78],{"class":77},[67,2151,989],{"class":84},[13,2153,2154,2155,2159,2160,2163,2164,2167],{},"詳細は",[23,2156,1509],{"href":2157,"rel":2158},"https:\u002F\u002Fjun-app.com\u002Fdocker-centos8\u002F",[27],"の記事にて解説します。centos8はデフォルトでコンテナ内でアクティブにならずwebサーバーも起動しません。ホストマシンの",[41,2161,2162],{},"systemd","をマウントし、そして",[41,2165,2166],{},"privileged: true","にてコンテナにroot権限を与えることで、コンテナのcentos8が動きます。",[2108,2169,2170],{"id":2170},"ポートを通す",[34,2172,2174],{"className":860,"code":2173,"filename":62,"language":862,"meta":43,"style":43},"ports: \n    - \"9000:80\"\n    - \"3000:3000\"\n",[41,2175,2176,2185,2195],{"__ignoreMap":43},[67,2177,2178,2181,2183],{"class":69,"line":70},[67,2179,2180],{"class":73},"ports",[67,2182,78],{"class":77},[67,2184,887],{"class":249},[67,2186,2187,2189,2191,2193],{"class":69,"line":91},[67,2188,2131],{"class":77},[67,2190,81],{"class":77},[67,2192,958],{"class":84},[67,2194,88],{"class":77},[67,2196,2197,2199,2201,2203],{"class":69,"line":98},[67,2198,2131],{"class":77},[67,2200,81],{"class":77},[67,2202,969],{"class":84},[67,2204,88],{"class":77},[13,2206,2207,2208,2211,2212,2215,2216,2219,2220,2222],{},"ここでホストマシンの",[41,2209,2210],{},"localhost:9000","と",[41,2213,2214],{},"localhost:3000","をコンテナの",[41,2217,2218],{},"localhost","、",[41,2221,2214],{},"につなげる様にします。ホストマシンを9000にしたのは気分です。干渉しなければ他のポートでも大丈夫です。",[598,2224,2226],{"id":2225},"dbの記述","DBの記述",[34,2228,2230],{"className":860,"code":2229,"filename":62,"language":862,"meta":43,"style":43},"db:\n    image: mysql:5.7\n    environment:\n      MYSQL_DATABASE: laravel_test\n      MYSQL_USER: test\n      MYSQL_PASSWORD: testtest\n      MYSQL_ROOT_PASSWORD: rootroot\n    ports: \n      - \"3306:3306\"\n    volumes: \n      - laravel_data:\u002Fvar\u002Flib\u002Fmysql\nvolumes: \n  laravel_data: {}\n",[41,2231,2232,2239,2247,2253,2262,2270,2278,2286,2294,2304,2312,2318,2326],{"__ignoreMap":43},[67,2233,2234,2237],{"class":69,"line":70},[67,2235,2236],{"class":73},"db",[67,2238,104],{"class":77},[67,2240,2241,2243,2245],{"class":69,"line":91},[67,2242,128],{"class":73},[67,2244,78],{"class":77},[67,2246,1005],{"class":84},[67,2248,2249,2251],{"class":69,"line":98},[67,2250,1010],{"class":73},[67,2252,104],{"class":77},[67,2254,2255,2257,2259],{"class":69,"line":107},[67,2256,1017],{"class":73},[67,2258,78],{"class":77},[67,2260,2261],{"class":84}," laravel_test\n",[67,2263,2264,2266,2268],{"class":69,"line":4},[67,2265,1027],{"class":73},[67,2267,78],{"class":77},[67,2269,1032],{"class":84},[67,2271,2272,2274,2276],{"class":69,"line":125},[67,2273,1037],{"class":73},[67,2275,78],{"class":77},[67,2277,1042],{"class":84},[67,2279,2280,2282,2284],{"class":69,"line":136},[67,2281,1047],{"class":73},[67,2283,78],{"class":77},[67,2285,1052],{"class":84},[67,2287,2288,2290,2292],{"class":69,"line":144},[67,2289,139],{"class":73},[67,2291,78],{"class":77},[67,2293,887],{"class":249},[67,2295,2296,2298,2300,2302],{"class":69,"line":153},[67,2297,147],{"class":77},[67,2299,81],{"class":77},[67,2301,1069],{"class":84},[67,2303,88],{"class":77},[67,2305,2306,2308,2310],{"class":69,"line":164},[67,2307,167],{"class":73},[67,2309,78],{"class":77},[67,2311,887],{"class":249},[67,2313,2314,2316],{"class":69,"line":172},[67,2315,147],{"class":77},[67,2317,1086],{"class":84},[67,2319,2320,2322,2324],{"class":69,"line":180},[67,2321,1092],{"class":73},[67,2323,78],{"class":77},[67,2325,887],{"class":249},[67,2327,2328,2330,2332],{"class":69,"line":188},[67,2329,1102],{"class":73},[67,2331,78],{"class":77},[67,2333,1107],{"class":77},[13,2335,2336,2337,2342],{},"DBはmysql:5.7の",[23,2338,2341],{"href":2339,"rel":2340},"https:\u002F\u002Fhub.docker.com\u002F_\u002Fmysql",[27],"公式イメージ","を使用します。パスワードの設定なども簡単に行ってくれます。そしてデータ内容は永続化したいのでlaravel_data:{}をボリュームしておきます。",[13,2344,2345],{},"DBはこれでOKです。もしDBにあるデータをまっさらにしたい場合はコンテナを止めて、ボリュームを削除すれば大丈夫です。",[51,2347,2348],{"id":2348},"laravelのプロジェクトソースの調整",[13,2350,2351,2352,2355],{},"以上でwebサーバーとDBサーバーの準備は整いました。次は",[41,2353,2354],{},"laravel","ソースと細かい調整を行います。まずはlaravelディレクトリにプロジェクトを入れます。今回はバージョン６を入れます。ローカルにはcomposerが入っているものとします。",[34,2357,2360],{"className":2358,"code":2359,"language":39},[37],"$ cd laravel\n$ composer create-project \"laravel\u002Flaravel=6.*\" .\n",[41,2361,2359],{"__ignoreMap":43},[13,2363,2364,2365,2368,2369,2371],{},"laravelのソースが並んだら",[41,2366,2367],{},".env","を以下の様にDBの設定を書き込みます。",[41,2370,62],{},"で設定した通りのパスワード、ユーザーです。",[34,2373,2376],{"className":2374,"code":2375,"filename":2367,"language":39,"meta":43},[37],"...\nDB_CONNECTION=mysql\nDB_HOST=db\nDB_PORT=3306\nDB_DATABASE=laravel_test\nDB_USERNAME=root\nDB_PASSWORD=rootroot\n...\n",[41,2377,2375],{"__ignoreMap":43},[13,2379,2380,2383,2384,2386,2387,2389],{},[41,2381,2382],{},"DB_HOST","は",[41,2385,62],{},"のserviceで定義した名前",[41,2388,2236],{},"で大丈夫です。こうすればマイグレーションができる様になります。",[598,2391,2393],{"id":2392},"httpdconfとphpiniの微調整","httpd.confとphp.iniの微調整",[13,2395,2396,2397,2400,2401,2403,2404,2407],{},"Laravelではドキュメントルート を ",[41,2398,2399],{},"\u002Fpublic"," 配下にする様に言われています。",[41,2402,1145],{},"のデフォルトのドキュメントルートは ",[41,2405,2406],{},"\u002Fvar\u002Fwww\u002Fhtml","なので以下の様に変更しておきます",[34,2409,2412],{"className":2410,"code":2411,"filename":1145,"language":39,"meta":43},[37],"DocumentRoot \"\u002Fvar\u002Fwww\u002Fhtml\u002Fpublic\"\n\n\u003CDirectory \"\u002Fvar\u002Fwww\u002Fhtml\u002Fpublic\">\n    Options Indexes FollowSymLinks\n    AllowOverride All\n    Require all granted\n\u003C\u002FDirectory>\n",[41,2413,2411],{"__ignoreMap":43},[13,2415,2416,2417,2420],{},"こうするとapacheは",[41,2418,2419],{},"\u002Fvar\u002Fwww\u002Fhtml\u002Fpublic","をドキュメントルートとして見てくれます。",[13,2422,2423],{},"php.iniはタイムゾーン をAsia\u002FTokyoにするだけです。",[51,2425,2427],{"id":2426},"composeを起動","composeを起動！",[13,2429,2430,2431,2434,2435,2437],{},"それでは",[41,2432,2433],{},"docker-compose","で起動します。",[41,2436,62],{},"がある場所にて以下の様に唱えます。",[34,2439,2442],{"className":2440,"code":2441,"language":39},[37],"$ docker-compose up -d\n",[41,2443,2441],{"__ignoreMap":43},[13,2445,2446,2447,2450],{},"ビルドがうまくいけば",[41,2448,2449],{},"docker ps","で2つのコンテナが起動しているのが確認できます。",[34,2452,2455],{"className":2453,"code":2454,"language":39},[37],"CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                          NAMES\n3e121d905e5e        centos_apache:1.0   \"\u002Fsbin\u002Finit\"             5 seconds ago       Up 3 seconds        0.0.0.0:3000->3000\u002Ftcp, 0.0.0.0:9000->80\u002Ftcp   centos_apache_web_1_1\nea5076e310e9        mysql:5.7           \"docker-entrypoint.s…\"   5 seconds ago       Up 4 seconds        0.0.0.0:3306->3306\u002Ftcp, 33060\u002Ftcp              centos_apache_db_1\n",[41,2456,2454],{"__ignoreMap":43},[13,2458,2459,2461],{},[41,2460,2210],{},"をブラウザでアクセスすると",[2463,2464],"image-render",{":src":2465,":width":2466},"'_mix\u002Fsch-2020-11-28-17.33.36-768x407.png'","'100%'",[13,2468,2469],{},"はい。おなじみのLaravelの画面が表示されました。マイグレーションをするためにコンテナに入ります。",[34,2471,2474],{"className":2472,"code":2473,"language":39},[37],"$ docker exec -it centos_apache_web_1_1 \u002Fbin\u002Fbash\n",[41,2475,2473],{"__ignoreMap":43},[13,2477,2478,2479,2482],{},"プロジェクトルートに移動して",[41,2480,2481],{},"php artisan migrate","を唱えるとDBコンテナへマイグレーションされます。",[34,2484,2487],{"className":2485,"code":2486,"language":39},[37],"$ cd \u002Fvar\u002Fwww\u002Fhtml\n$ ls\nREADME.md  artisan    client         composer.lock  database      nuxt.config.js     package.json  public     routes      storage  vendor\napp        bootstrap  composer.json  config         node_modules  package-lock.json  phpunit.xml   resources  server.php  tests    webpack.mix.js\n\n$ php artisan migrate\nMigration table created successfully.\nMigrating: 2014_10_12_000000_create_users_table\nMigrated:  2014_10_12_000000_create_users_table (0.03 seconds)\nMigrating: 2014_10_12_100000_create_password_resets_table\nMigrated:  2014_10_12_100000_create_password_resets_table (0.02 seconds)\nMigrating: 2019_08_19_000000_create_failed_jobs_table\nMigrated:  2019_08_19_000000_create_failed_jobs_table (0.01 seconds)\n",[41,2488,2486],{"__ignoreMap":43},[13,2490,2491],{},"本当に入ったかはDBコンテナに入ってmysqlコマンドを通じて中身を見ると確認できます。ここまでくればLaravelの環境構築は完了です。phpのバージョンを変えてみたりで、OS環境による検証もある程度楽になるでしょう。",[51,2493,2495],{"id":2494},"おまけnuxtjsを起動させる","（おまけ）Nuxt.jsを起動させる",[13,2497,2498],{},"一応私のプロジェクトではnuxt.jsを入れていたので、せっかくなので解説します。larvelディレクトリにてnuxt.jsのプロジェクトを作成します。（ローカルでも、コンテナ内でもどちらでも。私はローカルで作成）",[34,2500,2503],{"className":2501,"code":2502,"language":39},[37],"$ cd laravel\n$ npx create-nuxt-app client\n",[41,2504,2502],{"__ignoreMap":43},[13,2506,2507],{},"以下の様なディレクトリになりました。",[34,2509,2512],{"className":2510,"code":2511,"language":39},[37],".\n├── README.md\n├── app\n├── artisan\n├── bootstrap\n├── client # nuxt ソース\n├── composer.json\n├── composer.lock\n├── config\n├── database\n├── phpunit.xml\n├── public\n├── resources\n├── routes\n├── server.php\n├── storage\n├── tests\n├── vendor\n└── webpack.mix.js\n",[41,2513,2511],{"__ignoreMap":43},[13,2515,2516,2517,2520,2521,2524],{},"ちなみにLaravelに初期にあった",[41,2518,2519],{},"package.json","は削除しています。",[41,2522,2523],{},"client","ディレクトリ配下にnuxtのソースがありますが、これだと管理がしにくいので以下の様に変更します。",[34,2526,2529],{"className":2527,"code":2528,"language":39},[37],".\n├── README.md\n├── app\n├── artisan\n├── bootstrap\n├── client\n├── composer.json\n├── composer.lock\n├── config\n├── database\n├── node_modules #clientから\n├── nuxt.config.js #clientから\n├── package-lock.json #clientから\n├── package.json #clientから\n├── phpunit.xml\n├── public\n├── resources\n├── routes\n├── server.php\n├── storage\n├── tests\n├── vendor\n└── webpack.mix.js\n",[41,2530,2528],{"__ignoreMap":43},[13,2532,2533,2535,2536,2539],{},[41,2534,2523],{},"から4つのファイルを引っ張り出し、そして",[41,2537,2538],{},"nuxt.config.js","に以下を追記します。",[34,2541,2544],{"className":2542,"code":2543,"filename":2538,"language":39,"meta":43},[37],"srcDir: 'client\u002F',\n",[41,2545,2543],{"__ignoreMap":43},[13,2547,2548,2549,2551,2552,2555],{},"こうすることで",[41,2550,2523],{},"配下はnuxtのソースだけを置いて設定ファイルや",[41,2553,2554],{},"dist","はLaravelのプロジェクトルートに出される様にします。この辺はチームの好みによるので自由に変更してください。",[13,2557,2558,2559,2562,2563,2565],{},"そしてコンテナ内に入って ",[41,2560,2561],{},"npm run dev","をすればnuxtの開発サーバーが立ち上がるのですが、その前にまた",[41,2564,2538],{},"に以下の内容を記述します。",[34,2567,2570],{"className":2568,"code":2569,"filename":2538,"language":39,"meta":43},[37],"server: {\n    host: '0.0.0.0'\n},\n",[41,2571,2569],{"__ignoreMap":43},[13,2573,2574,2575,2577,2578,1747],{},"dockerコンテナを使用しない場合はこの設定は要らないのですが、コンテナ内で",[41,2576,2561],{},"をしてそれに接続するには上記の設定が必要です。コンテナ内のlocalhost:3000に開発サーバーが立ち上がります。",[41,2579,62],{},[34,2581,2583],{"className":860,"code":2582,"filename":62,"language":862,"meta":43,"style":43},"ports: \n    - \"9000:80\"\n    - \"3000:3000\n",[41,2584,2585,2593,2603],{"__ignoreMap":43},[67,2586,2587,2589,2591],{"class":69,"line":70},[67,2588,2180],{"class":73},[67,2590,78],{"class":77},[67,2592,887],{"class":249},[67,2594,2595,2597,2599,2601],{"class":69,"line":91},[67,2596,2131],{"class":77},[67,2598,81],{"class":77},[67,2600,958],{"class":84},[67,2602,88],{"class":77},[67,2604,2605,2607,2609],{"class":69,"line":98},[67,2606,2131],{"class":77},[67,2608,81],{"class":77},[67,2610,2611],{"class":84},"3000:3000\n",[13,2613,2614],{},"この様にホストの3000とコンテナの3000ポートをつないでいたので、localhost:3000にアクセスすると",[2463,2616],{":src":2617,":width":2466},"'_mix\u002Fsch-2020-11-28-18.02.48-768x599.png'",[13,2619,2620],{},"nuxtの画面が現れました。（UIフレームワークにvuetifyを選択するとこの画面になります。）これでnuxtの開発もコンテナ内で実行できます。",[809,2622,2623],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s-wAU, html code.shiki .s-wAU{--shiki-default:#F07178}html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .sfyAc, html code.shiki .sfyAc{--shiki-default:#C3E88D}html pre.shiki code .s0W1g, html code.shiki .s0W1g{--shiki-default:#BABED8}html pre.shiki code .sbqyR, html code.shiki .sbqyR{--shiki-default:#FF9CAC}",{"title":43,"searchDepth":98,"depth":98,"links":2625},[2626,2630,2637,2638,2645,2648,2649],{"id":848,"depth":91,"text":848,"children":2627},[2628,2629],{"id":1129,"depth":98,"text":1129},{"id":1156,"depth":98,"text":1156},{"id":1162,"depth":91,"text":1162,"children":2631},[2632,2633,2634,2635,2636],{"id":1420,"depth":98,"text":1421},{"id":1534,"depth":98,"text":1535},{"id":1602,"depth":98,"text":1603},{"id":1665,"depth":98,"text":1665},{"id":1704,"depth":98,"text":1705},{"id":1728,"depth":91,"text":1728},{"id":1760,"depth":91,"text":1760,"children":2639},[2640,2644],{"id":1996,"depth":98,"text":1996,"children":2641},[2642,2643],{"id":2110,"depth":107,"text":2110},{"id":2170,"depth":107,"text":2170},{"id":2225,"depth":98,"text":2226},{"id":2348,"depth":91,"text":2348,"children":2646},[2647],{"id":2392,"depth":98,"text":2393},{"id":2426,"depth":91,"text":2427},{"id":2494,"depth":91,"text":2495},[2651],"devstack","2026-01-16",{},"\u002Farticles\u002Fbuild-lamp-with-docker",{"title":837,"description":837},"articles\u002Fbuild-lamp-with-docker",[831,2354],"_mix\u002Fdokcer_laravel.jpeg","V2jA9dknjBNGZQzsV_h65rI9ap5VBJ9l1skOpFFoD8c",{"id":2661,"title":2662,"body":2663,"category":4638,"createdAt":4639,"description":4640,"extension":823,"index":91,"meta":4641,"navigation":94,"path":4642,"publish":94,"seo":4643,"series":4644,"seriesTitle":4645,"stem":4646,"tag":4647,"thumbnail":4649,"updatedAt":824,"__hash__":4650},"series\u002Fseries\u002Frtmp-manager-server-2.md","配信中継サーバ開発2：ffmpegを用いたyoutubeへのテスト配信とローカルデバッグ環境の構築",{"type":10,"value":2664,"toc":4617},[2665,2668,2671,2674,2685,2688,2691,2694,2711,2714,2717,2723,2726,2767,2786,3045,3048,3312,3314,3523,3529,3676,3679,4068,4071,4074,4077,4080,4173,4200,4203,4206,4213,4219,4225,4235,4239,4242,4246,4249,4261,4264,4267,4270,4276,4282,4286,4293,4299,4312,4315,4318,4321,4325,4328,4336,4340,4343,4346,4349,4352,4357,4360,4363,4366,4369,4372,4375,4378,4381,4392,4395,4398,4401,4404,4408,4411,4545,4555,4561,4567,4570,4573,4579,4586,4589,4592,4595,4598,4614],[13,2666,2667],{},"こんにちはjunです。前回の記事から2年も経ってしまいましたが、サイクリング欲が再度湧いてきたのでこの内容を完成させるように頑張ります。ではとりあえず前回はgoproからdockerのRTMPサーバに送信してローカルマシン上で見れるかを確かめました。最終的には以下のような構成を開発します。（その１のものと変わっています）",[2463,2669],{":src":2670,":width":2466},"'rtmp-docker-local\u002Ffig2.jpg'",[13,2672,2673],{},"今回の記事は",[1112,2675,2676,2679,2682],{},[1115,2677,2678],{},"上記図の環境をローカルでdockerで構築する",[1115,2680,2681],{},"管理用サーバ上のffmpegを用いてyoutubeにgoproの映像を中継してライブする",[1115,2683,2684],{},"ローカルで簡単に配信をデバッグできる環境を構築する\nの3点を解説したいと思います。",[13,2686,2687],{},"これらの内容をまずローカルで実装するためにDockerを用いて構築します。使用しているOSはmacOs Ventura 13.4.1でdockerは4.17.0です。また前回から2年たっているのでdockerfileなどを修正します。",[51,2689,2690],{"id":2690},"完成品",[13,2692,2693],{},"この記事でのゴールはこんな感じです。（字幕ON推奨）",[1579,2695,2696],{},[2697,2698,2699,2709],"no-ssr",{},[2700,2701],"iframe",{"width":2702,"height":2703,"src":2704,"title":2705,"frameBorder":2706,"allow":2707,"referrerPolicy":2708,"allowFullScreen":94},"100%","400px","https:\u002F\u002Fwww.youtube.com\u002Fembed\u002FTY61fzShv30?si=a72lxLH1mvLsYTma","YouTube video player","0","accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share","strict-origin-when-cross-origin",[2697,2710],{},[51,2712,2713],{"id":2713},"全ファイル構成",[13,2715,2716],{},"とりあえず完成した必要なファイルと構成を載せます。",[34,2718,2721],{"className":2719,"code":2720,"language":39},[37],".\n├── Dockerfile\n├── conf\n│   ├── 000-default.conf\n│   ├── default.conf\n│   └── nginx.conf\n├── debug\n│   └── index.html\n├── docker-compose.yml\n└── src\n    └── public\n        └── test.html\n",[41,2722,2720],{"__ignoreMap":43},[13,2724,2725],{},"Dockerfileは管理用コンテナの構成に変更。あとでwebフレームワークのlumenを入れるためにcomposerを入れています。（この回では入れません）。そしてffmpegを入れておきます。",[34,2727,2730],{"className":2728,"code":2729,"language":1138,"meta":43,"style":43},"language-Dockerfile shiki shiki-themes material-theme-ocean","FROM php:apache\nCOPY --from=composer \u002Fusr\u002Fbin\u002Fcomposer \u002Fusr\u002Fbin\u002Fcomposer\nRUN curl -O https:\u002F\u002Fjohnvansickle.com\u002Fffmpeg\u002Freleases\u002Fffmpeg-release-amd64-static.tar.xz && \\\n    tar -xJf ffmpeg-release-amd64-static.tar.xz && \\\n    mv ffmpeg-*\u002Fffmpeg \u002Fusr\u002Flocal\u002Fbin\u002F && \\\n    mv ffmpeg-*\u002Fffprobe \u002Fusr\u002Flocal\u002Fbin\u002F && \\\n    rm -rf ffmpeg-*\n",[41,2731,2732,2737,2742,2747,2752,2757,2762],{"__ignoreMap":43},[67,2733,2734],{"class":69,"line":70},[67,2735,2736],{},"FROM php:apache\n",[67,2738,2739],{"class":69,"line":91},[67,2740,2741],{},"COPY --from=composer \u002Fusr\u002Fbin\u002Fcomposer \u002Fusr\u002Fbin\u002Fcomposer\n",[67,2743,2744],{"class":69,"line":98},[67,2745,2746],{},"RUN curl -O https:\u002F\u002Fjohnvansickle.com\u002Fffmpeg\u002Freleases\u002Fffmpeg-release-amd64-static.tar.xz && \\\n",[67,2748,2749],{"class":69,"line":107},[67,2750,2751],{},"    tar -xJf ffmpeg-release-amd64-static.tar.xz && \\\n",[67,2753,2754],{"class":69,"line":4},[67,2755,2756],{},"    mv ffmpeg-*\u002Fffmpeg \u002Fusr\u002Flocal\u002Fbin\u002F && \\\n",[67,2758,2759],{"class":69,"line":125},[67,2760,2761],{},"    mv ffmpeg-*\u002Fffprobe \u002Fusr\u002Flocal\u002Fbin\u002F && \\\n",[67,2763,2764],{"class":69,"line":136},[67,2765,2766],{},"    rm -rf ffmpeg-*\n",[1112,2768,2769,2775,2781],{},[1115,2770,2771,2774],{},[41,2772,2773],{},"rtmptarget","がテスト配信先コンテナ",[1115,2776,2777,2780],{},[41,2778,2779],{},"rtmp","がGorpoなどからの受信用コンテナ",[1115,2782,2783,2785],{},[41,2784,1653],{},"が管理用web uiや配信媒体へ送信する処理を行うコンテナ",[34,2787,2789],{"className":860,"code":2788,"filename":62,"language":862,"meta":43,"style":43},"version: '2'\nservices:\n  rtmptarget:\n    image: tiangolo\u002Fnginx-rtmp\n    ports:\n      - \"1930:1935\"\n      - \"1931:80\"\n    volumes:\n      - .\u002Fconf\u002Fnginx.conf:\u002Fetc\u002Fnginx\u002Fnginx.conf\n      - .\u002Fconf\u002Fdefault.conf:\u002Fetc\u002Fnginx\u002Fconf.d\u002Fdefault.conf\n      - .\u002Fdebug:\u002Fusr\u002Fshare\u002Fnginx\u002F\n  rtmp:\n    image: tiangolo\u002Fnginx-rtmp\n    ports:\n      - \"1935:1935\"\n    volumes:\n      - shared_data:\u002Fusr\u002Fshare\u002Fnginx\u002Fhls\n      - .\u002Fconf\u002Fnginx.conf:\u002Fetc\u002Fnginx\u002Fnginx.conf\n  php:\n    build: .\n    expose:\n      - 1935\n    ports:\n      - \"8080:80\"\n    volumes:\n      - shared_data:\u002Fvar\u002Fwww\u002Fhtml\u002Fhls\n      - .\u002Fsrc:\u002Fvar\u002Fwww\u002Fhtml\n      - .\u002Fconf\u002F.htpasswd:\u002Fvar\u002Fwww\u002F.htpasswd\n      - .\u002Fconf\u002F000-default.conf:\u002Fetc\u002Fapache2\u002Fsites-enabled\u002F000-default.conf\n    extra_hosts:\n      - \"host.docker.internal:host-gateway\"\nvolumes:\n  shared_data:\n",[41,2790,2791,2804,2810,2817,2826,2832,2843,2854,2860,2867,2874,2881,2888,2896,2902,2913,2919,2926,2932,2939,2949,2956,2963,2969,2980,2986,2993,3000,3007,3014,3021,3032,3038],{"__ignoreMap":43},[67,2792,2793,2795,2797,2799,2802],{"class":69,"line":70},[67,2794,74],{"class":73},[67,2796,78],{"class":77},[67,2798,873],{"class":77},[67,2800,2801],{"class":84},"2",[67,2803,878],{"class":77},[67,2805,2806,2808],{"class":69,"line":91},[67,2807,101],{"class":73},[67,2809,104],{"class":77},[67,2811,2812,2815],{"class":69,"line":98},[67,2813,2814],{"class":73},"  rtmptarget",[67,2816,104],{"class":77},[67,2818,2819,2821,2823],{"class":69,"line":107},[67,2820,128],{"class":73},[67,2822,78],{"class":77},[67,2824,2825],{"class":84}," tiangolo\u002Fnginx-rtmp\n",[67,2827,2828,2830],{"class":69,"line":4},[67,2829,139],{"class":73},[67,2831,104],{"class":77},[67,2833,2834,2836,2838,2841],{"class":69,"line":125},[67,2835,147],{"class":77},[67,2837,81],{"class":77},[67,2839,2840],{"class":84},"1930:1935",[67,2842,88],{"class":77},[67,2844,2845,2847,2849,2852],{"class":69,"line":136},[67,2846,147],{"class":77},[67,2848,81],{"class":77},[67,2850,2851],{"class":84},"1931:80",[67,2853,88],{"class":77},[67,2855,2856,2858],{"class":69,"line":144},[67,2857,167],{"class":73},[67,2859,104],{"class":77},[67,2861,2862,2864],{"class":69,"line":153},[67,2863,147],{"class":77},[67,2865,2866],{"class":84}," .\u002Fconf\u002Fnginx.conf:\u002Fetc\u002Fnginx\u002Fnginx.conf\n",[67,2868,2869,2871],{"class":69,"line":164},[67,2870,147],{"class":77},[67,2872,2873],{"class":84}," .\u002Fconf\u002Fdefault.conf:\u002Fetc\u002Fnginx\u002Fconf.d\u002Fdefault.conf\n",[67,2875,2876,2878],{"class":69,"line":172},[67,2877,147],{"class":77},[67,2879,2880],{"class":84}," .\u002Fdebug:\u002Fusr\u002Fshare\u002Fnginx\u002F\n",[67,2882,2883,2886],{"class":69,"line":180},[67,2884,2885],{"class":73},"  rtmp",[67,2887,104],{"class":77},[67,2889,2890,2892,2894],{"class":69,"line":188},[67,2891,128],{"class":73},[67,2893,78],{"class":77},[67,2895,2825],{"class":84},[67,2897,2898,2900],{"class":69,"line":196},[67,2899,139],{"class":73},[67,2901,104],{"class":77},[67,2903,2904,2906,2908,2911],{"class":69,"line":204},[67,2905,147],{"class":77},[67,2907,81],{"class":77},[67,2909,2910],{"class":84},"1935:1935",[67,2912,88],{"class":77},[67,2914,2915,2917],{"class":69,"line":212},[67,2916,167],{"class":73},[67,2918,104],{"class":77},[67,2920,2921,2923],{"class":69,"line":467},[67,2922,147],{"class":77},[67,2924,2925],{"class":84}," shared_data:\u002Fusr\u002Fshare\u002Fnginx\u002Fhls\n",[67,2927,2928,2930],{"class":69,"line":497},[67,2929,147],{"class":77},[67,2931,2866],{"class":84},[67,2933,2934,2937],{"class":69,"line":503},[67,2935,2936],{"class":73},"  php",[67,2938,104],{"class":77},[67,2940,2941,2944,2946],{"class":69,"line":521},[67,2942,2943],{"class":73},"    build",[67,2945,78],{"class":77},[67,2947,2948],{"class":461}," .\n",[67,2950,2951,2954],{"class":69,"line":528},[67,2952,2953],{"class":73},"    expose",[67,2955,104],{"class":77},[67,2957,2958,2960],{"class":69,"line":540},[67,2959,147],{"class":77},[67,2961,2962],{"class":461}," 1935\n",[67,2964,2965,2967],{"class":69,"line":557},[67,2966,139],{"class":73},[67,2968,104],{"class":77},[67,2970,2971,2973,2975,2978],{"class":69,"line":562},[67,2972,147],{"class":77},[67,2974,81],{"class":77},[67,2976,2977],{"class":84},"8080:80",[67,2979,88],{"class":77},[67,2981,2982,2984],{"class":69,"line":568},[67,2983,167],{"class":73},[67,2985,104],{"class":77},[67,2987,2988,2990],{"class":69,"line":1089},[67,2989,147],{"class":77},[67,2991,2992],{"class":84}," shared_data:\u002Fvar\u002Fwww\u002Fhtml\u002Fhls\n",[67,2994,2995,2997],{"class":69,"line":1099},[67,2996,147],{"class":77},[67,2998,2999],{"class":84}," .\u002Fsrc:\u002Fvar\u002Fwww\u002Fhtml\n",[67,3001,3002,3004],{"class":69,"line":1302},[67,3003,147],{"class":77},[67,3005,3006],{"class":84}," .\u002Fconf\u002F.htpasswd:\u002Fvar\u002Fwww\u002F.htpasswd\n",[67,3008,3009,3011],{"class":69,"line":1308},[67,3010,147],{"class":77},[67,3012,3013],{"class":84}," .\u002Fconf\u002F000-default.conf:\u002Fetc\u002Fapache2\u002Fsites-enabled\u002F000-default.conf\n",[67,3015,3016,3019],{"class":69,"line":1313},[67,3017,3018],{"class":73},"    extra_hosts",[67,3020,104],{"class":77},[67,3022,3023,3025,3027,3030],{"class":69,"line":1319},[67,3024,147],{"class":77},[67,3026,81],{"class":77},[67,3028,3029],{"class":84},"host.docker.internal:host-gateway",[67,3031,88],{"class":77},[67,3033,3034,3036],{"class":69,"line":1324},[67,3035,1092],{"class":73},[67,3037,104],{"class":77},[67,3039,3040,3043],{"class":69,"line":1330},[67,3041,3042],{"class":73},"  shared_data",[67,3044,104],{"class":77},[13,3046,3047],{},"主にRTMPサーバ用の内容です。",[34,3049,3054],{"className":3050,"code":3051,"filename":3052,"language":3053,"meta":43,"style":43},"language-conf shiki shiki-themes material-theme-ocean","worker_processes  auto;\n\nerror_log  \u002Fvar\u002Flog\u002Fnginx\u002Ferror.log notice;\npid        \u002Fvar\u002Frun\u002Fnginx.pid;\n\n\nevents {\n    worker_connections  1024;\n}\n\nrtmp_auto_push on;\n\nrtmp {\n    server {\n        listen 1935;\n        listen [::]:1935 ipv6only=on;\n        access_log \u002Fvar\u002Flog\u002Frtmp_access.log;\n        chunk_size 4096;\n        timeout 10s;\n\n        application live {\n            live on;\n\n            # HLSの記述欄\n            hls on;\n            # ここに映像ファイルが配置される\n            hls_path \u002Fusr\u002Fshare\u002Fnginx\u002Fhls;\n            hls_fragment 10s;\n            hls_playlist_length 30s;\n        }\n    }\n}\n\n\n\nhttp {\n    include       \u002Fetc\u002Fnginx\u002Fmime.types;\n    default_type  application\u002Foctet-stream;\n\n    log_format  main  '$remote_addr - $remote_user [$time_local] \"$request\" '\n                      '$status $body_bytes_sent \"$http_referer\" '\n                      '\"$http_user_agent\" \"$http_x_forwarded_for\"';\n\n    access_log  \u002Fvar\u002Flog\u002Fnginx\u002Faccess.log  main;\n\n    sendfile        on;\n    #tcp_nopush     on;\n\n    keepalive_timeout  65;\n\n    #gzip  on;\n\n    include \u002Fetc\u002Fnginx\u002Fconf.d\u002F*.conf;\n}\n","conf\u002Fnginx.conf","conf",[41,3055,3056,3061,3065,3070,3075,3079,3083,3088,3093,3097,3101,3106,3110,3115,3120,3125,3130,3135,3140,3145,3149,3154,3159,3163,3168,3173,3178,3183,3188,3193,3197,3202,3206,3210,3214,3218,3223,3228,3233,3237,3242,3247,3252,3256,3261,3265,3270,3275,3279,3285,3290,3296,3301,3307],{"__ignoreMap":43},[67,3057,3058],{"class":69,"line":70},[67,3059,3060],{},"worker_processes  auto;\n",[67,3062,3063],{"class":69,"line":91},[67,3064,95],{"emptyLinePlaceholder":94},[67,3066,3067],{"class":69,"line":98},[67,3068,3069],{},"error_log  \u002Fvar\u002Flog\u002Fnginx\u002Ferror.log notice;\n",[67,3071,3072],{"class":69,"line":107},[67,3073,3074],{},"pid        \u002Fvar\u002Frun\u002Fnginx.pid;\n",[67,3076,3077],{"class":69,"line":4},[67,3078,95],{"emptyLinePlaceholder":94},[67,3080,3081],{"class":69,"line":125},[67,3082,95],{"emptyLinePlaceholder":94},[67,3084,3085],{"class":69,"line":136},[67,3086,3087],{},"events {\n",[67,3089,3090],{"class":69,"line":144},[67,3091,3092],{},"    worker_connections  1024;\n",[67,3094,3095],{"class":69,"line":153},[67,3096,571],{},[67,3098,3099],{"class":69,"line":164},[67,3100,95],{"emptyLinePlaceholder":94},[67,3102,3103],{"class":69,"line":172},[67,3104,3105],{},"rtmp_auto_push on;\n",[67,3107,3108],{"class":69,"line":180},[67,3109,95],{"emptyLinePlaceholder":94},[67,3111,3112],{"class":69,"line":188},[67,3113,3114],{},"rtmp {\n",[67,3116,3117],{"class":69,"line":196},[67,3118,3119],{},"    server {\n",[67,3121,3122],{"class":69,"line":204},[67,3123,3124],{},"        listen 1935;\n",[67,3126,3127],{"class":69,"line":212},[67,3128,3129],{},"        listen [::]:1935 ipv6only=on;\n",[67,3131,3132],{"class":69,"line":467},[67,3133,3134],{},"        access_log \u002Fvar\u002Flog\u002Frtmp_access.log;\n",[67,3136,3137],{"class":69,"line":497},[67,3138,3139],{},"        chunk_size 4096;\n",[67,3141,3142],{"class":69,"line":503},[67,3143,3144],{},"        timeout 10s;\n",[67,3146,3147],{"class":69,"line":521},[67,3148,95],{"emptyLinePlaceholder":94},[67,3150,3151],{"class":69,"line":528},[67,3152,3153],{},"        application live {\n",[67,3155,3156],{"class":69,"line":540},[67,3157,3158],{},"            live on;\n",[67,3160,3161],{"class":69,"line":557},[67,3162,95],{"emptyLinePlaceholder":94},[67,3164,3165],{"class":69,"line":562},[67,3166,3167],{},"            # HLSの記述欄\n",[67,3169,3170],{"class":69,"line":568},[67,3171,3172],{},"            hls on;\n",[67,3174,3175],{"class":69,"line":1089},[67,3176,3177],{},"            # ここに映像ファイルが配置される\n",[67,3179,3180],{"class":69,"line":1099},[67,3181,3182],{},"            hls_path \u002Fusr\u002Fshare\u002Fnginx\u002Fhls;\n",[67,3184,3185],{"class":69,"line":1302},[67,3186,3187],{},"            hls_fragment 10s;\n",[67,3189,3190],{"class":69,"line":1308},[67,3191,3192],{},"            hls_playlist_length 30s;\n",[67,3194,3195],{"class":69,"line":1313},[67,3196,565],{},[67,3198,3199],{"class":69,"line":1319},[67,3200,3201],{},"    }\n",[67,3203,3204],{"class":69,"line":1324},[67,3205,571],{},[67,3207,3208],{"class":69,"line":1330},[67,3209,95],{"emptyLinePlaceholder":94},[67,3211,3212],{"class":69,"line":1335},[67,3213,95],{"emptyLinePlaceholder":94},[67,3215,3216],{"class":69,"line":1341},[67,3217,95],{"emptyLinePlaceholder":94},[67,3219,3220],{"class":69,"line":1346},[67,3221,3222],{},"http {\n",[67,3224,3225],{"class":69,"line":1352},[67,3226,3227],{},"    include       \u002Fetc\u002Fnginx\u002Fmime.types;\n",[67,3229,3230],{"class":69,"line":1357},[67,3231,3232],{},"    default_type  application\u002Foctet-stream;\n",[67,3234,3235],{"class":69,"line":1363},[67,3236,95],{"emptyLinePlaceholder":94},[67,3238,3239],{"class":69,"line":1368},[67,3240,3241],{},"    log_format  main  '$remote_addr - $remote_user [$time_local] \"$request\" '\n",[67,3243,3244],{"class":69,"line":1374},[67,3245,3246],{},"                      '$status $body_bytes_sent \"$http_referer\" '\n",[67,3248,3249],{"class":69,"line":1379},[67,3250,3251],{},"                      '\"$http_user_agent\" \"$http_x_forwarded_for\"';\n",[67,3253,3254],{"class":69,"line":1384},[67,3255,95],{"emptyLinePlaceholder":94},[67,3257,3258],{"class":69,"line":1389},[67,3259,3260],{},"    access_log  \u002Fvar\u002Flog\u002Fnginx\u002Faccess.log  main;\n",[67,3262,3263],{"class":69,"line":1395},[67,3264,95],{"emptyLinePlaceholder":94},[67,3266,3267],{"class":69,"line":1400},[67,3268,3269],{},"    sendfile        on;\n",[67,3271,3272],{"class":69,"line":1406},[67,3273,3274],{},"    #tcp_nopush     on;\n",[67,3276,3277],{"class":69,"line":1411},[67,3278,95],{"emptyLinePlaceholder":94},[67,3280,3282],{"class":69,"line":3281},49,[67,3283,3284],{},"    keepalive_timeout  65;\n",[67,3286,3288],{"class":69,"line":3287},50,[67,3289,95],{"emptyLinePlaceholder":94},[67,3291,3293],{"class":69,"line":3292},51,[67,3294,3295],{},"    #gzip  on;\n",[67,3297,3299],{"class":69,"line":3298},52,[67,3300,95],{"emptyLinePlaceholder":94},[67,3302,3304],{"class":69,"line":3303},53,[67,3305,3306],{},"    include \u002Fetc\u002Fnginx\u002Fconf.d\u002F*.conf;\n",[67,3308,3310],{"class":69,"line":3309},54,[67,3311,571],{},[13,3313,3047],{},[34,3315,3318],{"className":3050,"code":3316,"filename":3317,"language":3053,"meta":43,"style":43},"server {\n    listen       80;\n    listen  [::]:80;\n    server_name  localhost;\n\n    #access_log  \u002Fvar\u002Flog\u002Fnginx\u002Fhost.access.log  main;\n\n    location \u002F {\n        root   \u002Fusr\u002Fshare\u002Fnginx;\n        index  index.html index.htm;\n    }\n\n    #error_page  404              \u002F404.html;\n\n    # redirect server error pages to the static page \u002F50x.html\n    #\n    error_page   500 502 503 504  \u002F50x.html;\n    location = \u002F50x.html {\n        root   \u002Fusr\u002Fshare\u002Fnginx;\n    }\n\n    # proxy the PHP scripts to Apache listening on 127.0.0.1:80\n    #\n    #location ~ \\.php$ {\n    #    proxy_pass   http:\u002F\u002F127.0.0.1;\n    #}\n\n    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000\n    #\n    #location ~ \\.php$ {\n    #    root           html;\n    #    fastcgi_pass   127.0.0.1:9000;\n    #    fastcgi_index  index.php;\n    #    fastcgi_param  SCRIPT_FILENAME  \u002Fscripts$fastcgi_script_name;\n    #    include        fastcgi_params;\n    #}\n\n    # deny access to .htaccess files, if Apache's document root\n    # concurs with nginx's one\n    #\n    #location ~ \u002F\\.ht {\n    #    deny  all;\n    #}\n}\n","conf\u002Fdefault.conf",[41,3319,3320,3325,3330,3335,3340,3344,3349,3353,3358,3363,3368,3372,3376,3381,3385,3390,3395,3400,3405,3409,3413,3417,3422,3426,3431,3436,3441,3445,3450,3454,3458,3463,3468,3473,3478,3483,3487,3491,3496,3501,3505,3510,3515,3519],{"__ignoreMap":43},[67,3321,3322],{"class":69,"line":70},[67,3323,3324],{},"server {\n",[67,3326,3327],{"class":69,"line":91},[67,3328,3329],{},"    listen       80;\n",[67,3331,3332],{"class":69,"line":98},[67,3333,3334],{},"    listen  [::]:80;\n",[67,3336,3337],{"class":69,"line":107},[67,3338,3339],{},"    server_name  localhost;\n",[67,3341,3342],{"class":69,"line":4},[67,3343,95],{"emptyLinePlaceholder":94},[67,3345,3346],{"class":69,"line":125},[67,3347,3348],{},"    #access_log  \u002Fvar\u002Flog\u002Fnginx\u002Fhost.access.log  main;\n",[67,3350,3351],{"class":69,"line":136},[67,3352,95],{"emptyLinePlaceholder":94},[67,3354,3355],{"class":69,"line":144},[67,3356,3357],{},"    location \u002F {\n",[67,3359,3360],{"class":69,"line":153},[67,3361,3362],{},"        root   \u002Fusr\u002Fshare\u002Fnginx;\n",[67,3364,3365],{"class":69,"line":164},[67,3366,3367],{},"        index  index.html index.htm;\n",[67,3369,3370],{"class":69,"line":172},[67,3371,3201],{},[67,3373,3374],{"class":69,"line":180},[67,3375,95],{"emptyLinePlaceholder":94},[67,3377,3378],{"class":69,"line":188},[67,3379,3380],{},"    #error_page  404              \u002F404.html;\n",[67,3382,3383],{"class":69,"line":196},[67,3384,95],{"emptyLinePlaceholder":94},[67,3386,3387],{"class":69,"line":204},[67,3388,3389],{},"    # redirect server error pages to the static page \u002F50x.html\n",[67,3391,3392],{"class":69,"line":212},[67,3393,3394],{},"    #\n",[67,3396,3397],{"class":69,"line":467},[67,3398,3399],{},"    error_page   500 502 503 504  \u002F50x.html;\n",[67,3401,3402],{"class":69,"line":497},[67,3403,3404],{},"    location = \u002F50x.html {\n",[67,3406,3407],{"class":69,"line":503},[67,3408,3362],{},[67,3410,3411],{"class":69,"line":521},[67,3412,3201],{},[67,3414,3415],{"class":69,"line":528},[67,3416,95],{"emptyLinePlaceholder":94},[67,3418,3419],{"class":69,"line":540},[67,3420,3421],{},"    # proxy the PHP scripts to Apache listening on 127.0.0.1:80\n",[67,3423,3424],{"class":69,"line":557},[67,3425,3394],{},[67,3427,3428],{"class":69,"line":562},[67,3429,3430],{},"    #location ~ \\.php$ {\n",[67,3432,3433],{"class":69,"line":568},[67,3434,3435],{},"    #    proxy_pass   http:\u002F\u002F127.0.0.1;\n",[67,3437,3438],{"class":69,"line":1089},[67,3439,3440],{},"    #}\n",[67,3442,3443],{"class":69,"line":1099},[67,3444,95],{"emptyLinePlaceholder":94},[67,3446,3447],{"class":69,"line":1302},[67,3448,3449],{},"    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000\n",[67,3451,3452],{"class":69,"line":1308},[67,3453,3394],{},[67,3455,3456],{"class":69,"line":1313},[67,3457,3430],{},[67,3459,3460],{"class":69,"line":1319},[67,3461,3462],{},"    #    root           html;\n",[67,3464,3465],{"class":69,"line":1324},[67,3466,3467],{},"    #    fastcgi_pass   127.0.0.1:9000;\n",[67,3469,3470],{"class":69,"line":1330},[67,3471,3472],{},"    #    fastcgi_index  index.php;\n",[67,3474,3475],{"class":69,"line":1335},[67,3476,3477],{},"    #    fastcgi_param  SCRIPT_FILENAME  \u002Fscripts$fastcgi_script_name;\n",[67,3479,3480],{"class":69,"line":1341},[67,3481,3482],{},"    #    include        fastcgi_params;\n",[67,3484,3485],{"class":69,"line":1346},[67,3486,3440],{},[67,3488,3489],{"class":69,"line":1352},[67,3490,95],{"emptyLinePlaceholder":94},[67,3492,3493],{"class":69,"line":1357},[67,3494,3495],{},"    # deny access to .htaccess files, if Apache's document root\n",[67,3497,3498],{"class":69,"line":1363},[67,3499,3500],{},"    # concurs with nginx's one\n",[67,3502,3503],{"class":69,"line":1368},[67,3504,3394],{},[67,3506,3507],{"class":69,"line":1374},[67,3508,3509],{},"    #location ~ \u002F\\.ht {\n",[67,3511,3512],{"class":69,"line":1379},[67,3513,3514],{},"    #    deny  all;\n",[67,3516,3517],{"class":69,"line":1384},[67,3518,3440],{},[67,3520,3521],{"class":69,"line":1389},[67,3522,571],{},[13,3524,3525,3526,3528],{},"管理用コンテナに使用します。ドキュメントルートが",[41,3527,2419],{},"なのは後でlumenを入れるためです。",[34,3530,3533],{"className":3050,"code":3531,"filename":3532,"language":3053,"meta":43,"style":43},"\u003CVirtualHost *:80>\n    # The ServerName directive sets the request scheme, hostname and port that\n    # the server uses to identify itself. This is used when creating\n    # redirection URLs. In the context of virtual hosts, the ServerName\n    # specifies what hostname must appear in the request's Host: header to\n    # match this virtual host. For the default virtual host (this file) this\n    # value is not decisive as it is used as a last resort host regardless.\n    # However, you must set it for any further virtual host explicitly.\n    #ServerName www.example.com\n\n    ServerAdmin webmaster@localhost\n    DocumentRoot \u002Fvar\u002Fwww\u002Fhtml\u002Fpublic\n\n    # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,\n    # error, crit, alert, emerg.\n    # It is also possible to configure the loglevel for particular\n    # modules, e.g.\n    #LogLevel info ssl:warn\n\n    ErrorLog ${APACHE_LOG_DIR}\u002Ferror.log\n    CustomLog ${APACHE_LOG_DIR}\u002Faccess.log combined\n\n    # For most configuration files from conf-available\u002F, which are\n    # enabled or disabled at a global level, it is possible to\n    # include a line for only one particular virtual host. For example the\n    # following line enables the CGI configuration for this host only\n    # after it has been globally disabled with \"a2disconf\".\n    #Include conf-available\u002Fserve-cgi-bin.conf\n\u003C\u002FVirtualHost>\n","conf\u002F000-default.conf",[41,3534,3535,3540,3545,3550,3555,3560,3565,3570,3575,3580,3584,3589,3594,3598,3603,3608,3613,3618,3623,3627,3632,3637,3641,3646,3651,3656,3661,3666,3671],{"__ignoreMap":43},[67,3536,3537],{"class":69,"line":70},[67,3538,3539],{},"\u003CVirtualHost *:80>\n",[67,3541,3542],{"class":69,"line":91},[67,3543,3544],{},"    # The ServerName directive sets the request scheme, hostname and port that\n",[67,3546,3547],{"class":69,"line":98},[67,3548,3549],{},"    # the server uses to identify itself. This is used when creating\n",[67,3551,3552],{"class":69,"line":107},[67,3553,3554],{},"    # redirection URLs. In the context of virtual hosts, the ServerName\n",[67,3556,3557],{"class":69,"line":4},[67,3558,3559],{},"    # specifies what hostname must appear in the request's Host: header to\n",[67,3561,3562],{"class":69,"line":125},[67,3563,3564],{},"    # match this virtual host. For the default virtual host (this file) this\n",[67,3566,3567],{"class":69,"line":136},[67,3568,3569],{},"    # value is not decisive as it is used as a last resort host regardless.\n",[67,3571,3572],{"class":69,"line":144},[67,3573,3574],{},"    # However, you must set it for any further virtual host explicitly.\n",[67,3576,3577],{"class":69,"line":153},[67,3578,3579],{},"    #ServerName www.example.com\n",[67,3581,3582],{"class":69,"line":164},[67,3583,95],{"emptyLinePlaceholder":94},[67,3585,3586],{"class":69,"line":172},[67,3587,3588],{},"    ServerAdmin webmaster@localhost\n",[67,3590,3591],{"class":69,"line":180},[67,3592,3593],{},"    DocumentRoot \u002Fvar\u002Fwww\u002Fhtml\u002Fpublic\n",[67,3595,3596],{"class":69,"line":188},[67,3597,95],{"emptyLinePlaceholder":94},[67,3599,3600],{"class":69,"line":196},[67,3601,3602],{},"    # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,\n",[67,3604,3605],{"class":69,"line":204},[67,3606,3607],{},"    # error, crit, alert, emerg.\n",[67,3609,3610],{"class":69,"line":212},[67,3611,3612],{},"    # It is also possible to configure the loglevel for particular\n",[67,3614,3615],{"class":69,"line":467},[67,3616,3617],{},"    # modules, e.g.\n",[67,3619,3620],{"class":69,"line":497},[67,3621,3622],{},"    #LogLevel info ssl:warn\n",[67,3624,3625],{"class":69,"line":503},[67,3626,95],{"emptyLinePlaceholder":94},[67,3628,3629],{"class":69,"line":521},[67,3630,3631],{},"    ErrorLog ${APACHE_LOG_DIR}\u002Ferror.log\n",[67,3633,3634],{"class":69,"line":528},[67,3635,3636],{},"    CustomLog ${APACHE_LOG_DIR}\u002Faccess.log combined\n",[67,3638,3639],{"class":69,"line":540},[67,3640,95],{"emptyLinePlaceholder":94},[67,3642,3643],{"class":69,"line":557},[67,3644,3645],{},"    # For most configuration files from conf-available\u002F, which are\n",[67,3647,3648],{"class":69,"line":562},[67,3649,3650],{},"    # enabled or disabled at a global level, it is possible to\n",[67,3652,3653],{"class":69,"line":568},[67,3654,3655],{},"    # include a line for only one particular virtual host. For example the\n",[67,3657,3658],{"class":69,"line":1089},[67,3659,3660],{},"    # following line enables the CGI configuration for this host only\n",[67,3662,3663],{"class":69,"line":1099},[67,3664,3665],{},"    # after it has been globally disabled with \"a2disconf\".\n",[67,3667,3668],{"class":69,"line":1302},[67,3669,3670],{},"    #Include conf-available\u002Fserve-cgi-bin.conf\n",[67,3672,3673],{"class":69,"line":1308},[67,3674,3675],{},"\u003C\u002FVirtualHost>\n",[13,3677,3678],{},"とりあえず確認したい時に使用します。",[34,3680,3685],{"className":3681,"code":3682,"filename":3683,"language":3684,"meta":43,"style":43},"language-html shiki shiki-themes material-theme-ocean","\u003C!DOCTYPE html>\n\u003Chtml>\n\n\u003Chead>\n  \u003Cmeta charset=\"utf-8\">\n  \u003Ctitle>MediaElement\u003C\u002Ftitle>\n  \u003C!-- MediaElement style -->\n  \u003Clink rel=\"stylesheet\" href=\"\u002F\u002Fcdnjs.cloudflare.com\u002Fajax\u002Flibs\u002Fmediaelement\u002F4.2.9\u002Fmediaelementplayer.css\" \u002F>\n\u003C\u002Fhead>\n\n\u003Cbody>\n  \u003C!-- MediaElement -->\n  \u003Cscript src=\"\u002F\u002Fcdnjs.cloudflare.com\u002Fajax\u002Flibs\u002Fmediaelement\u002F4.2.9\u002Fmediaelement-and-player.js\">\u003C\u002Fscript>\n\n  \u003Cvideo id=\"player\" width=\"640\" height=\"360\">\n\u003C\u002Fbody>\n\u003Cscript type=\"text\u002Fjavascript\">\n\n      var player = new MediaElementPlayer('player', {\n        success: function(mediaElement, originalNode) {\n          console.log(\"Player initialised\");\n        }\n      });\n        player.setSrc(\"\u002Fhls\u002F.m3u8\");\n\u003C\u002Fscript>\n\n\u003C\u002Fhtml>\n","src\u002Fpublic\u002Ftest.html,debug\u002Findex.html","html",[41,3686,3687,3701,3710,3714,3723,3745,3765,3770,3804,3812,3816,3825,3830,3856,3860,3905,3913,3933,3937,3965,3989,4012,4016,4025,4048,4056,4060],{"__ignoreMap":43},[67,3688,3689,3692,3695,3698],{"class":69,"line":70},[67,3690,3691],{"class":77},"\u003C!",[67,3693,3694],{"class":73},"DOCTYPE",[67,3696,3697],{"class":245}," html",[67,3699,3700],{"class":77},">\n",[67,3702,3703,3706,3708],{"class":69,"line":91},[67,3704,3705],{"class":77},"\u003C",[67,3707,3684],{"class":73},[67,3709,3700],{"class":77},[67,3711,3712],{"class":69,"line":98},[67,3713,95],{"emptyLinePlaceholder":94},[67,3715,3716,3718,3721],{"class":69,"line":107},[67,3717,3705],{"class":77},[67,3719,3720],{"class":73},"head",[67,3722,3700],{"class":77},[67,3724,3725,3728,3731,3734,3736,3738,3741,3743],{"class":69,"line":4},[67,3726,3727],{"class":77},"  \u003C",[67,3729,3730],{"class":73},"meta",[67,3732,3733],{"class":245}," charset",[67,3735,253],{"class":77},[67,3737,314],{"class":77},[67,3739,3740],{"class":84},"utf-8",[67,3742,314],{"class":77},[67,3744,3700],{"class":77},[67,3746,3747,3749,3752,3755,3758,3761,3763],{"class":69,"line":125},[67,3748,3727],{"class":77},[67,3750,3751],{"class":73},"title",[67,3753,3754],{"class":77},">",[67,3756,3757],{"class":249},"MediaElement",[67,3759,3760],{"class":77},"\u003C\u002F",[67,3762,3751],{"class":73},[67,3764,3700],{"class":77},[67,3766,3767],{"class":69,"line":136},[67,3768,3769],{"class":751},"  \u003C!-- MediaElement style -->\n",[67,3771,3772,3774,3777,3780,3782,3784,3787,3789,3792,3794,3796,3799,3801],{"class":69,"line":144},[67,3773,3727],{"class":77},[67,3775,3776],{"class":73},"link",[67,3778,3779],{"class":245}," rel",[67,3781,253],{"class":77},[67,3783,314],{"class":77},[67,3785,3786],{"class":84},"stylesheet",[67,3788,314],{"class":77},[67,3790,3791],{"class":245}," href",[67,3793,253],{"class":77},[67,3795,314],{"class":77},[67,3797,3798],{"class":84},"\u002F\u002Fcdnjs.cloudflare.com\u002Fajax\u002Flibs\u002Fmediaelement\u002F4.2.9\u002Fmediaelementplayer.css",[67,3800,314],{"class":77},[67,3802,3803],{"class":77}," \u002F>\n",[67,3805,3806,3808,3810],{"class":69,"line":153},[67,3807,3760],{"class":77},[67,3809,3720],{"class":73},[67,3811,3700],{"class":77},[67,3813,3814],{"class":69,"line":164},[67,3815,95],{"emptyLinePlaceholder":94},[67,3817,3818,3820,3823],{"class":69,"line":172},[67,3819,3705],{"class":77},[67,3821,3822],{"class":73},"body",[67,3824,3700],{"class":77},[67,3826,3827],{"class":69,"line":180},[67,3828,3829],{"class":751},"  \u003C!-- MediaElement -->\n",[67,3831,3832,3834,3837,3840,3842,3844,3847,3849,3852,3854],{"class":69,"line":188},[67,3833,3727],{"class":77},[67,3835,3836],{"class":73},"script",[67,3838,3839],{"class":245}," src",[67,3841,253],{"class":77},[67,3843,314],{"class":77},[67,3845,3846],{"class":84},"\u002F\u002Fcdnjs.cloudflare.com\u002Fajax\u002Flibs\u002Fmediaelement\u002F4.2.9\u002Fmediaelement-and-player.js",[67,3848,314],{"class":77},[67,3850,3851],{"class":77},">\u003C\u002F",[67,3853,3836],{"class":73},[67,3855,3700],{"class":77},[67,3857,3858],{"class":69,"line":196},[67,3859,95],{"emptyLinePlaceholder":94},[67,3861,3862,3864,3867,3870,3872,3874,3877,3879,3882,3884,3886,3889,3891,3894,3896,3898,3901,3903],{"class":69,"line":204},[67,3863,3727],{"class":77},[67,3865,3866],{"class":73},"video",[67,3868,3869],{"class":245}," id",[67,3871,253],{"class":77},[67,3873,314],{"class":77},[67,3875,3876],{"class":84},"player",[67,3878,314],{"class":77},[67,3880,3881],{"class":245}," width",[67,3883,253],{"class":77},[67,3885,314],{"class":77},[67,3887,3888],{"class":84},"640",[67,3890,314],{"class":77},[67,3892,3893],{"class":245}," height",[67,3895,253],{"class":77},[67,3897,314],{"class":77},[67,3899,3900],{"class":84},"360",[67,3902,314],{"class":77},[67,3904,3700],{"class":77},[67,3906,3907,3909,3911],{"class":69,"line":212},[67,3908,3760],{"class":77},[67,3910,3822],{"class":73},[67,3912,3700],{"class":77},[67,3914,3915,3917,3919,3922,3924,3926,3929,3931],{"class":69,"line":467},[67,3916,3705],{"class":77},[67,3918,3836],{"class":73},[67,3920,3921],{"class":245}," type",[67,3923,253],{"class":77},[67,3925,314],{"class":77},[67,3927,3928],{"class":84},"text\u002Fjavascript",[67,3930,314],{"class":77},[67,3932,3700],{"class":77},[67,3934,3935],{"class":69,"line":497},[67,3936,95],{"emptyLinePlaceholder":94},[67,3938,3939,3942,3945,3947,3950,3953,3955,3957,3959,3961,3963],{"class":69,"line":503},[67,3940,3941],{"class":245},"      var",[67,3943,3944],{"class":249}," player ",[67,3946,253],{"class":77},[67,3948,3949],{"class":77}," new",[67,3951,3952],{"class":256}," MediaElementPlayer",[67,3954,260],{"class":249},[67,3956,263],{"class":77},[67,3958,3876],{"class":84},[67,3960,263],{"class":77},[67,3962,350],{"class":77},[67,3964,299],{"class":77},[67,3966,3967,3970,3972,3975,3977,3980,3982,3985,3987],{"class":69,"line":521},[67,3968,3969],{"class":256},"        success",[67,3971,78],{"class":77},[67,3973,3974],{"class":245}," function",[67,3976,260],{"class":77},[67,3978,3979],{"class":346},"mediaElement",[67,3981,350],{"class":77},[67,3983,3984],{"class":346}," originalNode",[67,3986,356],{"class":77},[67,3988,299],{"class":77},[67,3990,3991,3994,3996,3999,4001,4003,4006,4008,4010],{"class":69,"line":528},[67,3992,3993],{"class":249},"          console",[67,3995,426],{"class":77},[67,3997,3998],{"class":256},"log",[67,4000,260],{"class":73},[67,4002,314],{"class":77},[67,4004,4005],{"class":84},"Player initialised",[67,4007,314],{"class":77},[67,4009,356],{"class":73},[67,4011,282],{"class":77},[67,4013,4014],{"class":69,"line":540},[67,4015,565],{"class":77},[67,4017,4018,4021,4023],{"class":69,"line":557},[67,4019,4020],{"class":77},"      }",[67,4022,356],{"class":249},[67,4024,282],{"class":77},[67,4026,4027,4030,4032,4035,4037,4039,4042,4044,4046],{"class":69,"line":562},[67,4028,4029],{"class":249},"        player",[67,4031,426],{"class":77},[67,4033,4034],{"class":256},"setSrc",[67,4036,260],{"class":249},[67,4038,314],{"class":77},[67,4040,4041],{"class":84},"\u002Fhls\u002F.m3u8",[67,4043,314],{"class":77},[67,4045,356],{"class":249},[67,4047,282],{"class":77},[67,4049,4050,4052,4054],{"class":69,"line":568},[67,4051,3760],{"class":77},[67,4053,3836],{"class":73},[67,4055,3700],{"class":77},[67,4057,4058],{"class":69,"line":1089},[67,4059,95],{"emptyLinePlaceholder":94},[67,4061,4062,4064,4066],{"class":69,"line":1099},[67,4063,3760],{"class":77},[67,4065,3684],{"class":73},[67,4067,3700],{"class":77},[13,4069,4070],{},"では上記のファイルを用いて解説します。",[51,4072,4073],{"id":4073},"共有ボリュームを用いて受信した映像を扱う",[13,4075,4076],{},"まずは受信用コンテナから得られたGoproの映像を管理用コンテナで使用できるようにします。受信用コンテナにPHPなどを入れようとしましたが結構面倒だったので、別のコンテナとして独立させました。しかしそのままでは受信した映像データ（HLS）を共有できないため、受信用コンテナで生成されるHLSファイルを共有ボリュームで共有します。",[13,4078,4079],{},"その設定のために",[34,4081,4083],{"className":860,"code":4082,"filename":62,"language":862,"meta":43,"style":43},"version: '2'\nservices:\n  #...\n  rtmp:\n    #...\n    volumes:\n      - shared_data:\u002Fusr\u002Fshare\u002Fnginx\u002Fhls\n    #...\n  php:\n    #...\n    volumes:\n      - shared_data:\u002Fvar\u002Fwww\u002Fhtml\u002Fhls\n    #...\nvolumes:\n  shared_data:\n",[41,4084,4085,4097,4103,4108,4114,4119,4125,4131,4135,4141,4145,4151,4157,4161,4167],{"__ignoreMap":43},[67,4086,4087,4089,4091,4093,4095],{"class":69,"line":70},[67,4088,74],{"class":73},[67,4090,78],{"class":77},[67,4092,873],{"class":77},[67,4094,2801],{"class":84},[67,4096,878],{"class":77},[67,4098,4099,4101],{"class":69,"line":91},[67,4100,101],{"class":73},[67,4102,104],{"class":77},[67,4104,4105],{"class":69,"line":98},[67,4106,4107],{"class":751},"  #...\n",[67,4109,4110,4112],{"class":69,"line":107},[67,4111,2885],{"class":73},[67,4113,104],{"class":77},[67,4115,4116],{"class":69,"line":4},[67,4117,4118],{"class":751},"    #...\n",[67,4120,4121,4123],{"class":69,"line":125},[67,4122,167],{"class":73},[67,4124,104],{"class":77},[67,4126,4127,4129],{"class":69,"line":136},[67,4128,147],{"class":77},[67,4130,2925],{"class":84},[67,4132,4133],{"class":69,"line":144},[67,4134,4118],{"class":751},[67,4136,4137,4139],{"class":69,"line":153},[67,4138,2936],{"class":73},[67,4140,104],{"class":77},[67,4142,4143],{"class":69,"line":164},[67,4144,4118],{"class":751},[67,4146,4147,4149],{"class":69,"line":172},[67,4148,167],{"class":73},[67,4150,104],{"class":77},[67,4152,4153,4155],{"class":69,"line":180},[67,4154,147],{"class":77},[67,4156,2992],{"class":84},[67,4158,4159],{"class":69,"line":188},[67,4160,4118],{"class":751},[67,4162,4163,4165],{"class":69,"line":196},[67,4164,1092],{"class":73},[67,4166,104],{"class":77},[67,4168,4169,4171],{"class":69,"line":204},[67,4170,3042],{"class":73},[67,4172,104],{"class":77},[13,4174,4175,4177,4178,4180,4181,4184,4185,4188,4189,4192,4193,4195,4196,4199],{},[41,4176,1092],{},"でボリュームを定義してそのボリューム名を各コンテナに配置するパスを指定します。すると",[41,4179,2779],{},"（受信用コンテナ）では",[41,4182,4183],{},"\u002Fusr\u002Fshare\u002Fnginx\u002Fhls"," に",[41,4186,4187],{},"*.ts","ファイルや",[41,4190,4191],{},".m3u8","ファイルが作成されます。そして",[41,4194,1653],{},"（管理用コンテナ）では",[41,4197,4198],{},"\u002Fvar\u002Fwww\u002Fhtml\u002Fhls","に同じファイル群が作成されます。",[13,4201,4202],{},"管理用コンテナでgoproから受信したデータをffmpegで色々したり、読み取ったり、配信できるようになりました。",[598,4204,4205],{"id":4205},"テストしてみる",[13,4207,4208,4209,4212],{},"その１の記事または後述するOBSの方法を参考にGopro・OBSから",[41,4210,4211],{},"rtmp:\u002F\u002FYOUR_PC_IP\u002Flive"," にRTMP送信をします。",[34,4214,4217],{"className":4215,"code":4216,"language":39},[37],"# \u003CYOUR_PHP_CONTAINER_NAME>はあなたの環境の管理用コンテナ名に書き換えてください。\n\ndocker exec -it \u003CYOUR_PHP_CONTAINER_NAME> \u002Fbin\u002Fbash\n",[41,4218,4216],{"__ignoreMap":43},[13,4220,4221,4222,4224],{},"ボリュームのため、",[41,4223,4198],{},"というディレクトリがあると思います。そしてGoproでの収録を開始するとディレクトリ内にファイルが配置されます。",[13,4226,1562,4227,4230,4231,4234],{},[41,4228,4229],{},"\u002Fvar\u002Fwww\u002Fhtml\u002Fpublic\u002Ftest.html","があるので",[41,4232,4233],{},"http:\u002F\u002Flocalhost:8080","でweb playerを用いて確認できるはずです。",[51,4236,4238],{"id":4237},"ffmpegを用いてyoutubeに送信してみる","ffmpegを用いてYoutubeに送信してみる",[13,4240,4241],{},"次にffmpegを用いて管理用コンテナからyoutube liveに流してみます。ffmpegはlinux上で動画、音声の変換・記録・再生・配信を行うことができるOSSです。今はコマンド上で配信をするだけですが、最終的にはffmpegを利用して管理画面から配信内容を制御する予定です。現時点で自分もまだ詳細なプロパティーや映像系の知識に乏しいので、調べた際のコマンドのコピペやchat gptで調査した内容になります。",[598,4243,4245],{"id":4244},"youtube-のライブを始めておく","youtube のライブを始めておく",[13,4247,4248],{},"本記事では簡単に述べておきます。すでにGoogle、Youtubeアカウントがありライブストリーミングが有効になっている前提とします。",[4250,4251,4252,4255,4258],"ol",{},[1115,4253,4254],{},"Youtubeに移動し、右上の「＋」ボタンをクリックして「ライブ配信を開始」を選択",[1115,4256,4257],{},"ライブ配信の設定からストリームURLとストリームキーを控えます。ライブストリームキーとURLは「rtmp:\u002F\u002Fa.rtmp.youtube.com\u002Flive2\u002FLIVE_KEY」とURLの後につければOKです。ただしドメインのとこはyoutubeのrtmp配信サーバのipにしておいてください（調べ方と理由は後述）",[1115,4259,4260],{},"Youtubeのライブ管理画面では「ライブ配信を公開するには、ストリーミング ソフトで動画の送信を開始します」という表示がされています。ffmpegでRTMP送信をすれば表示されます。",[13,4262,4263],{},"プライバシーを非公開にしておくことをおすすめします。",[598,4265,4266],{"id":4266},"コマンドを打つ",[13,4268,4269],{},"Goproからの映像をローカルで確認できたらとりあえず以下のコマンドを管理用コンテナ内から打ってみてください。",[34,4271,4274],{"className":4272,"code":4273,"language":39},[37],"ffmpeg -re -i \"\u002Fvar\u002Fwww\u002Fhtml\u002Fhls\u002F.m3u8\" -c:a aac -ar 44100 -ab 128k -ac 2 -strict -2 -flags +global_header -bsf:a aac_adtstoasc -f flv \"rtmp:\u002F\u002F64.233.189.134\u002Flive2\u002FYOUR_LIVE_KEY\"\n",[41,4275,4273],{"__ignoreMap":43},[13,4277,4278,4281],{},[41,4279,4280],{},"YOUR_LIVE_KEY"," はyoutuebのライブストリームキーを使用してください。ffmpegが起動してyoutubeにデータが送信されます。20秒ぐらいするとGoproからの映像の配信が開始されるはずです。",[598,4283,4285],{"id":4284},"dnsエラー","DNSエラー？",[13,4287,4288,4289,4292],{},"本来ライブストリームURLには",[41,4290,4291],{},"a.rtmp.youtube.com","というドメインを使用すべきですが、私のdockerで管理用コンテナから実行するとffmpegが以下のようなDNSエラーが発生します。",[34,4294,4297],{"className":4295,"code":4296,"language":39},[37],"[tcp @ 0x696d2c0] Failed to resolve hostname a.rtmp.youtube.com: System error\n[rtmp @ 0x696d480] Cannot open connection tcp:\u002F\u002Fa.rtmp.youtube.com:1935?tcp_nodelay=0\n[out#0\u002Fflv @ 0x6890880] Error opening output rtmp:\u002F\u002Fa.rtmp.youtube.com\u002Flive2\u002Fefth-usbu-ye2g-f0sk-a7ta: Input\u002Foutput error\nError opening output file rtmp:\u002F\u002Fa.rtmp.youtube.com\u002Flive2\u002Fefth-usbu-ye2g-f0sk-a7ta.\nError opening output files: Input\u002Foutput error\n",[41,4298,4296],{"__ignoreMap":43},[13,4300,4301,4302,4304,4305,4308,4309,4311],{},"ホストマシン上でffmpegを使用すると問題なく配信できるますが、docker内から行うとなぜか",[41,4303,4291],{},"のホストが見つからないというエラーが発生します。そのためホストマシンで",[41,4306,4307],{},"nslookup","を使用して",[41,4310,4291],{},"のIPを調べて、直接IPを指定したら問題なく動作しました。",[13,4313,4314],{},"ここはdockerの問題かつまだ調査中です。Googleなどはこの辺のIPをころころ変えてきそうなので、最終的にはきちんとドメインを利用できるようにしますがとりあえず今はIPで指定します。",[51,4316,4317],{"id":4317},"ローカルでデバッグしやすい環境にする",[13,4319,4320],{},"ひととおり受信→中継→配信を行えるdockerコンテナが構築できました。しかし毎回goproを起動したり、youtube liveを開始するのは面倒ですし、複数人で開発する時に機材がなかったり送信先が重複してします。そのため開発用にデバッグできるように送信元、配信先をローカルで実現できるようにします。",[598,4322,4324],{"id":4323},"送信元にgoproの代わりにobsを利用する","送信元にgoproの代わりにOBSを利用する",[13,4326,4327],{},"この記事では送信元としてGoproを使用してホストマシンの受信用コンテナにRTMPを送信しています。ですがこれはOBSなどの配信ソフトを利用することで簡単に代替できます。",[13,4329,4330,4331],{},"OBSはフリーのライブ配信や録画が行えます。PC上のウィンドウキャプチャをしたり、機材をそろえればnintedo switchなどのゲーム機の映像を配信することができます。とりあえずOBSをインストールして、webカメラなりウィンドウキャプチャを映像・音声ソースとして利用します。",[23,4332,4335],{"href":4333,"rel":4334},"https:\u002F\u002Fobsproject.com\u002Fja\u002Fdownload",[27],"OBSのインストールはこちらから",[2108,4337,4339],{"id":4338},"とりあえずmacの映像と音声を受信用rtmpに流そう","とりあえずmacの映像と音声を受信用RTMPに流そう",[13,4341,4342],{},"OBSをインストールしたらアプリを開きます。以下のような似た画面になっているはずです。（すでに設定がいくつかあるのは気にしないでください）",[2463,4344],{":src":4345,":width":2466},"'rtmp-docker-local\u002Fobs1.png'",[13,4347,4348],{},"「シーン」に何もなければ「＋」をクリックしてシーンを追加します。そして映像・音声ソースも追加していきます。「ソース」のとこの「＋」をクリックして「映像キャプチャデバイス」を選択します。",[13,4350,4351],{},"ソースのラベルを適当に入れておきます。",[2463,4353],{":src":4354,":width":4355,":center":4356},"'rtmp-docker-local\u002Fobs2.png'","'400px'","true",[13,4358,4359],{},"ソースの選択画面に移動するので「デバイス」から「FaceTime HDカメラ」などを選択しておきます。",[2463,4361],{":src":4362,":width":2466},"'rtmp-docker-local\u002Fobs3.png'",[13,4364,4365],{},"これだとまだ映像しか拾わないので次は「ソース」のとこの「＋」をクリックして「音声入力キャプチャ」を選択します。同じようにソースのラベルを適当に入れておきます。ソースの選択画面に移動するので「デバイス」から「既定」などを選択しておきます。どれでもとりあえず音声が取得できればOKです。",[2463,4367],{":src":4368,":width":2466},"'rtmp-docker-local\u002Fobs4.png'",[13,4370,4371],{},"こんな感じで映像となんか奇声を発して「音声入力キャプチャ」が反応していればOKです。",[2463,4373],{":src":4374,":width":2466},"'rtmp-docker-local\u002Fobs5.png'",[13,4376,4377],{},"次に配信の設定をします。OBS→「設定」を開いて配信のタブをクリックします。\nサービスから「カスタム」を選択します。",[2463,4379],{":src":4380,":width":2466},"'rtmp-docker-local\u002Fobs6.png'",[13,4382,4383,4384,4387,4388,4391],{},"そして「サーバー」に受信用コンテナのRTMPパスをいれます。このとき",[41,4385,4386],{},"127.0.0.1","というローカルループバックアドレスにしておきます。localhostにするとうまくいかない時があります。自分は",[41,4389,4390],{},"localhost:1935","に受信用コンテナのエンドポイントが控えていますが、違うポートの時はそのポートを指定してください。「適用」をクリックして「OK」をクリックします。",[2463,4393],{":src":4394,":width":2466},"'rtmp-docker-local\u002Fobs7.png'",[13,4396,4397],{},"最初の画面にもどったら「配信開始」をクリックすると配信されます。下の方にこのような表示がされていたり、確認用playerで確認したり、HLSファイルが生成されていれば成功しています。",[2463,4399],{":src":4400,":width":2466},"'rtmp-docker-local\u002Fobs8.png'",[13,4402,4403],{},"終了する時は「配信終了」をクリックします。",[51,4405,4407],{"id":4406},"配信先にローカルの別のrtmpサーバを使用する","配信先にローカルの別のRTMPサーバを使用する。",[13,4409,4410],{},"最後に配信先のRTMPサーバをローカルに用意します。一番簡単な方法としてはもう1つRTMPサーバを立ててしまうことです。気をつける点としては管理用コンテナから配信先のホストを指定できるようにします。",[34,4412,4414],{"className":860,"code":4413,"filename":62,"language":862,"meta":43,"style":43},"version: '2'\nservices:\n  rtmptarget:\n    image: tiangolo\u002Fnginx-rtmp\n    ports:\n      - \"1930:1935\"\n      - \"1931:80\"\n    volumes:\n      - .\u002Fconf\u002Fnginx.conf:\u002Fetc\u002Fnginx\u002Fnginx.conf\n      - .\u002Fconf\u002Fdefault.conf:\u002Fetc\u002Fnginx\u002Fconf.d\u002Fdefault.conf\n      - .\u002Fdebug:\u002Fusr\u002Fshare\u002Fnginx\u002F\n    # ...\n  php:\n    # ...\n    extra_hosts:\n      - \"host.docker.internal:host-gateway\"\n    # ...\nvolumes:\n  shared_data:\n",[41,4415,4416,4428,4434,4440,4448,4454,4464,4474,4480,4486,4492,4498,4503,4509,4513,4519,4529,4533,4539],{"__ignoreMap":43},[67,4417,4418,4420,4422,4424,4426],{"class":69,"line":70},[67,4419,74],{"class":73},[67,4421,78],{"class":77},[67,4423,873],{"class":77},[67,4425,2801],{"class":84},[67,4427,878],{"class":77},[67,4429,4430,4432],{"class":69,"line":91},[67,4431,101],{"class":73},[67,4433,104],{"class":77},[67,4435,4436,4438],{"class":69,"line":98},[67,4437,2814],{"class":73},[67,4439,104],{"class":77},[67,4441,4442,4444,4446],{"class":69,"line":107},[67,4443,128],{"class":73},[67,4445,78],{"class":77},[67,4447,2825],{"class":84},[67,4449,4450,4452],{"class":69,"line":4},[67,4451,139],{"class":73},[67,4453,104],{"class":77},[67,4455,4456,4458,4460,4462],{"class":69,"line":125},[67,4457,147],{"class":77},[67,4459,81],{"class":77},[67,4461,2840],{"class":84},[67,4463,88],{"class":77},[67,4465,4466,4468,4470,4472],{"class":69,"line":136},[67,4467,147],{"class":77},[67,4469,81],{"class":77},[67,4471,2851],{"class":84},[67,4473,88],{"class":77},[67,4475,4476,4478],{"class":69,"line":144},[67,4477,167],{"class":73},[67,4479,104],{"class":77},[67,4481,4482,4484],{"class":69,"line":153},[67,4483,147],{"class":77},[67,4485,2866],{"class":84},[67,4487,4488,4490],{"class":69,"line":164},[67,4489,147],{"class":77},[67,4491,2873],{"class":84},[67,4493,4494,4496],{"class":69,"line":172},[67,4495,147],{"class":77},[67,4497,2880],{"class":84},[67,4499,4500],{"class":69,"line":180},[67,4501,4502],{"class":751},"    # ...\n",[67,4504,4505,4507],{"class":69,"line":188},[67,4506,2936],{"class":73},[67,4508,104],{"class":77},[67,4510,4511],{"class":69,"line":196},[67,4512,4502],{"class":751},[67,4514,4515,4517],{"class":69,"line":204},[67,4516,3018],{"class":73},[67,4518,104],{"class":77},[67,4520,4521,4523,4525,4527],{"class":69,"line":212},[67,4522,147],{"class":77},[67,4524,81],{"class":77},[67,4526,3029],{"class":84},[67,4528,88],{"class":77},[67,4530,4531],{"class":69,"line":467},[67,4532,4502],{"class":751},[67,4534,4535,4537],{"class":69,"line":497},[67,4536,1092],{"class":73},[67,4538,104],{"class":77},[67,4540,4541,4543],{"class":69,"line":503},[67,4542,3042],{"class":73},[67,4544,104],{"class":77},[13,4546,4547,4548,4551,4552,4554],{},"管理用コンテナのプロパティに",[41,4549,4550],{},"extra_hosts","に",[41,4553,3029],{},"を加えることで、コンテナから利用できるホストマシンの特殊なIPアドレスがコンテナのhostsに追記されます。",[13,4556,4557,4560],{},[41,4558,4559],{},"cat \u002Fetc\u002Fhosts","を管理用サーバで実行すると追加したhostのIPがあるはずです。",[34,4562,4565],{"className":4563,"code":4564,"language":39},[37],"127.0.0.1       localhost\n::1     localhost ip6-localhost ip6-loopback\nfe00::0 ip6-localnet\nff00::0 ip6-mcastprefix\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters\n192.168.65.2    host.docker.internal ←これ\n172.23.0.3      8227ce3421ec\n",[41,4566,4564],{"__ignoreMap":43},[598,4568,4569],{"id":4569},"ffmpegを実行する",[13,4571,4572],{},"次に配信先のRTMPコンテナに向けてffmpegを用いて配信します。ローカルのホスト、ポート、パスに合わせればいいだけですが以下のコマンドを使用します。（youtubeの時とすこし違います！！）",[34,4574,4577],{"className":4575,"code":4576,"language":39},[37],"ffmpeg -re -i \"\u002Fvar\u002Fwww\u002Fhtml\u002Fhls\u002F.m3u8\" -c:v libx264 -preset ultrafast -c:a aac -ar 44100 -ab 128k -ac 2 -f flv \"rtmp:\u002F\u002F192.168.65.2:1930\u002Flive\"\n",[41,4578,4576],{"__ignoreMap":43},[13,4580,4581,4582,4585],{},"このコマンドを打って配信先コンテナの確認用htmlのプレイヤー",[41,4583,4584],{},"http:\u002F\u002Flocalhost:1931\u002Findex.html","から映像を確認できれば受信できています。（20秒ほど待つといいです）",[13,4587,4588],{},"すこしオプションの内容がyoutubeのときと違っている理由として、単純にyoutubeのIPから変えればいいと思っていたらなぜかweb playerで映像が見れず音声しか流れなかったのが原因です。色々探ってこのコマンドにしたら問題なくいけました。もしかするとIPだけ変更してyoutubeもこのコマンドでやったらほうがいいかもしれません。検証中です。",[51,4590,4591],{"id":4591},"まとめと参考文献",[13,4593,4594],{},"記事は以上となります。一通り管理用の中継コンテナを用いてgoproの映像をffmpegでyoutubeに送信したり、ローカルの開発環境を整えました。次回はffmpegを用いて任意のシーンに切り替えたり、goproからの映像が途絶えた時などの例外処理を加えていくwebシステム部分をphpを使用して実装しようと思います。",[13,4596,4597],{},"今回参考にした資料です。",[1112,4599,4600,4607],{},[1115,4601,4602],{},[23,4603,4606],{"href":4604,"rel":4605},"https:\u002F\u002Fgist.github.com\u002Fqntmpkts\u002F403a027a4bfe99812ebf8952c41f8789",[27],"Restream m3u8 stream with ffmpeg to youtube live",[1115,4608,4609],{},[23,4610,4613],{"href":4611,"rel":4612},"https:\u002F\u002Fqiita.com\u002FCyberRex\u002Fitems\u002F960bbd0f348ad8dca544",[27],"FFmpegでよく使う例、コーデックをまとめてみた（2023年版）",[809,4615,4616],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s-wAU, html code.shiki .s-wAU{--shiki-default:#F07178}html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .sfyAc, html code.shiki .sfyAc{--shiki-default:#C3E88D}html pre.shiki code .sx098, html code.shiki .sx098{--shiki-default:#F78C6C}html pre.shiki code .sJ14y, html code.shiki .sJ14y{--shiki-default:#C792EA}html pre.shiki code .s0W1g, html code.shiki .s0W1g{--shiki-default:#BABED8}html pre.shiki code .sC9rS, html code.shiki .sC9rS{--shiki-default:#464B5D;--shiki-default-font-style:italic}html pre.shiki code .sdLwU, html code.shiki .sdLwU{--shiki-default:#82AAFF}html pre.shiki code .s7ZW3, html code.shiki .s7ZW3{--shiki-default:#BABED8;--shiki-default-font-style:italic}",{"title":43,"searchDepth":98,"depth":98,"links":4618},[4619,4620,4621,4624,4629,4634,4637],{"id":2690,"depth":91,"text":2690},{"id":2713,"depth":91,"text":2713},{"id":4073,"depth":91,"text":4073,"children":4622},[4623],{"id":4205,"depth":98,"text":4205},{"id":4237,"depth":91,"text":4238,"children":4625},[4626,4627,4628],{"id":4244,"depth":98,"text":4245},{"id":4266,"depth":98,"text":4266},{"id":4284,"depth":98,"text":4285},{"id":4317,"depth":91,"text":4317,"children":4630},[4631],{"id":4323,"depth":98,"text":4324,"children":4632},[4633],{"id":4338,"depth":107,"text":4339},{"id":4406,"depth":91,"text":4407,"children":4635},[4636],{"id":4569,"depth":98,"text":4569},{"id":4591,"depth":91,"text":4591},[2651],"2024-07-09","youtbeへの配信テストとデバッグ環境構築",{},"\u002Fseries\u002Frtmp-manager-server-2",{"title":2662,"description":4640},"rtmp-manager-server","Goproの配信映像を中継してyoutubeへの配信を管理するwebシステムを開発する","series\u002Frtmp-manager-server-2",[831,4648],"nginx","rtmp-docker-local\u002Fobs5.png","HPFKEu4iBy3O40z_uOHtY7Ed_jACJ4aBXKcnLMlAOLo",{"id":4652,"title":4653,"body":4654,"category":5969,"createdAt":5970,"description":5971,"extension":823,"index":70,"meta":5972,"navigation":94,"path":5973,"publish":94,"seo":5974,"series":4644,"seriesTitle":4645,"stem":5975,"tag":5976,"thumbnail":5977,"updatedAt":824,"__hash__":5978},"series\u002Fseries\u002Frtmp-manager-server-1.md","配信中継サーバ開発1：ローカルのDockerとNginxを用いてGoproからRTMPで送信されたライブ配信映像を再生する",{"type":10,"value":4655,"toc":5942},[4656,4660,4663,4666,4669,4672,4683,4686,4689,4700,4708,4710,4713,4716,4719,4722,4725,4728,4731,4742,4745,4756,4760,4763,4767,4774,4778,4781,4793,4799,4802,4817,4826,4830,4923,4926,4929,4932,4935,5153,5160,5163,5244,5250,5252,5259,5441,5444,5447,5453,5790,5796,5799,5805,5808,5812,5816,5819,5830,5833,5836,5839,5851,5858,5864,5873,5876,5879,5882,5886,5892,5896,5903,5906,5909,5912,5915,5918,5940],[1579,4657,4659],{"className":4658},[1582,1583],"\nこの記事はもともと[https:\u002F\u002Fjun-app.com\u002Farticles\u002Frtmp-docker-local](https:\u002F\u002Fjun-app.com\u002Farticles\u002Frtmp-docker-local) にて掲載していました。この記事に関連する内容をシリーズ化するため、このURLに移動しました。\n",[13,4661,4662],{},"こんにちはjunです。今回の記事は一風変わって物理世界をちょっと扱います。いつもはPC内で行えることばかりやっていますが、今回はGoproをつかってタイトルの通りライブ映像を再生したいと思います。RTMPサーバーをローカルで作成し、そこに送信できるかのテストをしてみたかった感じです。",[13,4664,4665],{},"ローカルPCのDockerにNignxをインストールしてRTMPの設定をしてブラウザから見れるようにします。この記事ではまずなぜ、このようなことを始めたいのかという理由から述べます。実装内容をさっさと知りたい方は「RTMPサーバー実装」へ移動してください。",[51,4667,4668],{"id":4668},"事の経緯",[13,4670,4671],{},"経緯としては私がyoutubeライブをやりたくなったからです笑。単純にyoutubeライブをやりたいだけならば、さっさとwebカメラからやればいいのですが、私はサイクリングが趣味でなのでその風景をライブしたいと思っていました。持っているアクションカメラがGoproであり、一応公式のスマホアプリを使用することでyoutubeライブをすることができるのですが以下の懸念がありました。",[1112,4673,4674,4677,4680],{},[1115,4675,4676],{},"Gopro、スマホアプリなどカメラ側の不具合によるライブの中断",[1115,4678,4679],{},"柔軟なカメラ切り替えを行える環境の準備",[1115,4681,4682],{},"スマホからのyoutubeライブ配信は登録者が50人必要（１番の障壁です笑）",[598,4684,4685],{"id":4685},"カメラ側によるライブの中断",[13,4687,4688],{},"Goproは簡単にライブ配信ができるのですが、以下の様なカメラ・スマホ側の要因によってライブが中断される可能性があります。",[1112,4690,4691,4694,4697],{},[1115,4692,4693],{},"Goproの熱暴走",[1115,4695,4696],{},"トンネルなどでwi-fi・ネットワーク切断",[1115,4698,4699],{},"カメラ、スマホの電池切れ",[13,4701,4702,4703,4707],{},"本当に中断されるかは ",[4704,4705,4706],"strong",{},"未検証"," ですが可能性があるのでこれを避けるためには「Gopro側からライブの設定を制御するのでなく、Goproからは音声と映像を取得するのみで配信は別環境で行う」ことがベストな気がします。",[598,4709,4679],{"id":4679},[13,4711,4712],{},"ライブ配信では映しっぱなしでもいいのですが、撮影禁止の箇所だったり環境によって映像のON\u002FOFFを切り替えたいと思っています。Goproアプリは確かにライブ配信は簡単なのですが、より細かい設定や制御は実装されていません。",[598,4714,4715],{"id":4715},"登録者が50人必要",[13,4717,4718],{},"スマホ通じてライブ配信をする場合はどうやら50人が必要でしたが、RTMPやPCからであれば0人でもOKでした。",[13,4720,4721],{},"登録者的な問題だったり、より細かい制御を実装するために以下のような構成を考えた結果、まずは自前RTMPサーバーへの映像の送信と再生ができるかをテストしてみたかった次第です。最終的にはRTMPサーバーから映像を取得してyoutubeに流します。サーバーでは映像の表示制御やyoutubeのコメント読み上げなど配信に関係する機能を管理するものとします。",[2463,4723],{":src":4724,":width":2466},"'rtmp-docker-local\u002Ffig.png'",[51,4726,4727],{"id":4727},"実装概要",[13,4729,4730],{},"この記事での目標は",[4250,4732,4733,4736,4739],{},[1115,4734,4735],{},"Goproからの映像をアプリを通じてコンテナ内のWebサーバーにRTMP通信で映像を送信。",[1115,4737,4738],{},"映像をドキュメントルートへ配置。",[1115,4740,4741],{},"webブラウザからアクセスして映像を見れうようにする。",[13,4743,4744],{},"まずはRTMPサーバーの実装を行います。使用しているOSはmacOs Catalina 10.15.5でdockerは3.5.2です。実装の手順としては",[4250,4746,4747,4750,4753],{},[1115,4748,4749],{},"Dockerを用いてRTMPとwebが可能なNginxを構築する。",[1115,4751,4752],{},"RTMPの設定をする。",[1115,4754,4755],{},"web側でHLSにて映像をvideoタグを用いて再生する。",[598,4757,4759],{"id":4758},"rtmpとは","RTMPとは？",[13,4761,4762],{},"ここまで出ているRTMPとはReal Time Messaging ProtocolのことでTCP上のプロトコルで映像、音声、データを細かいフラグメントに分けてストリーミング送信ができます。今回のようなリアルタイムに映像を撮影してサーバーに送信する際にも利用されます。",[598,4764,4766],{"id":4765},"なぜnginx","なぜNginx？",[13,4768,4769,4770,4773],{},"NginxではRTMPモジュールというのがあり、インストールしてconfファイルに少し記述するだけで1935ポートに",[41,4771,4772],{},"rtmp:\u002F\u002Fexample.com\u002Flive","のようなURLでサーバーに送信できます。",[51,4775,4777],{"id":4776},"rtmpサーバー実装","RTMPサーバー実装",[598,4779,4780],{"id":4780},"docker-composeの作成",[13,4782,4783,4784,4787,4788,2211,4790,4792],{},"では早速やっていきましょう。",[41,4785,4786],{},"rtmptest","みたいな適当なディレクトリを作成して、",[41,4789,1138],{},[41,4791,62],{},"ファイルを作成します。また、webとconfファイルを格納してボリュームしておくディレクトリも作成します。",[34,4794,4797],{"className":4795,"code":4796,"language":39},[37],"mkdir rtmptest\ncd rtmptest\n\ntouch Dockerfile docker-compose.yml\nmkdir html conf\n",[41,4798,4796],{"__ignoreMap":43},[13,4800,4801],{},"Dockerfileは以下のようにしておきます。",[34,4803,4805],{"className":2728,"code":4804,"language":1138,"meta":43,"style":43},"FROM tiangolo\u002Fnginx-rtmp\nVOLUME [\"\u002Fusr\u002Fshare\u002Fnginx\u002Fhtml\",\"\u002Fetc\u002Fnginx\"]\n",[41,4806,4807,4812],{"__ignoreMap":43},[67,4808,4809],{"class":69,"line":70},[67,4810,4811],{},"FROM tiangolo\u002Fnginx-rtmp\n",[67,4813,4814],{"class":69,"line":91},[67,4815,4816],{},"VOLUME [\"\u002Fusr\u002Fshare\u002Fnginx\u002Fhtml\",\"\u002Fetc\u002Fnginx\"]\n",[13,4818,4819,4820,4825],{},"今回は",[23,4821,4824],{"href":4822,"rel":4823},"https:\u002F\u002Fhub.docker.com\u002Fr\u002Ftiangolo\u002Fnginx-rtmp\u002F",[27],"rtmpの設定があるnginxのイメージ","を利用します。",[13,4827,4828,1766],{},[41,4829,62],{},[34,4831,4834],{"className":60,"code":4832,"filename":4833,"language":63,"meta":43,"style":43},"version: '2'\nservices:\n  app:\n    build: .\n    ports:\n      - \"8085:80\"\n      - \"1935:1935\"\n    volumes:\n      -  .\u002Fhtml:\u002Fusr\u002Fshare\u002Fnginx\u002Fhtml\n      -  .\u002Fconf\u002Fnginx.conf:\u002Fetc\u002Fnginx\u002Fnginx.conf\n      -  .\u002Fconf\u002Fdefault.conf:\u002Fetc\u002Fnginx\u002Fconf.d\u002Fdefault.conf\n","docke-compose.yml",[41,4835,4836,4848,4854,4861,4869,4875,4886,4896,4902,4909,4916],{"__ignoreMap":43},[67,4837,4838,4840,4842,4844,4846],{"class":69,"line":70},[67,4839,74],{"class":73},[67,4841,78],{"class":77},[67,4843,873],{"class":77},[67,4845,2801],{"class":84},[67,4847,878],{"class":77},[67,4849,4850,4852],{"class":69,"line":91},[67,4851,101],{"class":73},[67,4853,104],{"class":77},[67,4855,4856,4859],{"class":69,"line":98},[67,4857,4858],{"class":73},"  app",[67,4860,104],{"class":77},[67,4862,4863,4865,4867],{"class":69,"line":107},[67,4864,2943],{"class":73},[67,4866,78],{"class":77},[67,4868,2948],{"class":461},[67,4870,4871,4873],{"class":69,"line":4},[67,4872,139],{"class":73},[67,4874,104],{"class":77},[67,4876,4877,4879,4881,4884],{"class":69,"line":125},[67,4878,147],{"class":77},[67,4880,81],{"class":77},[67,4882,4883],{"class":84},"8085:80",[67,4885,88],{"class":77},[67,4887,4888,4890,4892,4894],{"class":69,"line":136},[67,4889,147],{"class":77},[67,4891,81],{"class":77},[67,4893,2910],{"class":84},[67,4895,88],{"class":77},[67,4897,4898,4900],{"class":69,"line":144},[67,4899,167],{"class":73},[67,4901,104],{"class":77},[67,4903,4904,4906],{"class":69,"line":153},[67,4905,147],{"class":77},[67,4907,4908],{"class":84},"  .\u002Fhtml:\u002Fusr\u002Fshare\u002Fnginx\u002Fhtml\n",[67,4910,4911,4913],{"class":69,"line":164},[67,4912,147],{"class":77},[67,4914,4915],{"class":84},"  .\u002Fconf\u002Fnginx.conf:\u002Fetc\u002Fnginx\u002Fnginx.conf\n",[67,4917,4918,4920],{"class":69,"line":172},[67,4919,147],{"class":77},[67,4921,4922],{"class":84},"  .\u002Fconf\u002Fdefault.conf:\u002Fetc\u002Fnginx\u002Fconf.d\u002Fdefault.conf\n",[598,4924,4925],{"id":4925},"confファイル調整",[13,4927,4928],{},"nginxのconfファイルを調整してRTMPとwebアクセスができるようにします。",[2108,4930,4931],{"id":2779},"RTMP",[13,4933,4934],{},"RTMPはnginx.confというapacheで言うhttp.confに以下のように記述します。",[34,4936,4938],{"className":3050,"code":4937,"filename":3052,"language":3053,"meta":43,"style":43},"worker_processes  auto;\n\nerror_log  \u002Fvar\u002Flog\u002Fnginx\u002Ferror.log notice;\npid        \u002Fvar\u002Frun\u002Fnginx.pid;\n\n\nevents {\n    worker_connections  1024;\n}\n\nrtmp_auto_push on;\n\nrtmp {\n    server {\n        listen 1935;\n        listen [::]:1935 ipv6only=on;\n        access_log \u002Fvar\u002Flog\u002Frtmp_access.log;\n        chunk_size 4096;\n        timeout 10s;\n\n        application live {\n            live on;\n\n            # HLSの記述欄\n            hls on;\n            # ここに映像ファイルが配置される\n            hls_path \u002Fusr\u002Fshare\u002Fnginx\u002Fhtml\u002Fhls;\n            hls_fragment 10s;\n        }\n    }\n}\n\n\n\nhttp {\n    include       \u002Fetc\u002Fnginx\u002Fmime.types;\n    default_type  application\u002Foctet-stream;\n\n    log_format  main  '$remote_addr - $remote_user [$time_local] \"$request\" '\n                      '$status $body_bytes_sent \"$http_referer\" '\n                      '\"$http_user_agent\" \"$http_x_forwarded_for\"';\n\n    access_log  \u002Fvar\u002Flog\u002Fnginx\u002Faccess.log  main;\n\n    sendfile        on;\n    #tcp_nopush     on;\n\n    keepalive_timeout  65;\n\n    #gzip  on;\n\n    include \u002Fetc\u002Fnginx\u002Fconf.d\u002F*.conf;\n}\n",[41,4939,4940,4944,4948,4952,4956,4960,4964,4968,4972,4976,4980,4984,4988,4992,4996,5000,5004,5008,5012,5016,5020,5024,5028,5032,5036,5040,5044,5049,5053,5057,5061,5065,5069,5073,5077,5081,5085,5089,5093,5097,5101,5105,5109,5113,5117,5121,5125,5129,5133,5137,5141,5145,5149],{"__ignoreMap":43},[67,4941,4942],{"class":69,"line":70},[67,4943,3060],{},[67,4945,4946],{"class":69,"line":91},[67,4947,95],{"emptyLinePlaceholder":94},[67,4949,4950],{"class":69,"line":98},[67,4951,3069],{},[67,4953,4954],{"class":69,"line":107},[67,4955,3074],{},[67,4957,4958],{"class":69,"line":4},[67,4959,95],{"emptyLinePlaceholder":94},[67,4961,4962],{"class":69,"line":125},[67,4963,95],{"emptyLinePlaceholder":94},[67,4965,4966],{"class":69,"line":136},[67,4967,3087],{},[67,4969,4970],{"class":69,"line":144},[67,4971,3092],{},[67,4973,4974],{"class":69,"line":153},[67,4975,571],{},[67,4977,4978],{"class":69,"line":164},[67,4979,95],{"emptyLinePlaceholder":94},[67,4981,4982],{"class":69,"line":172},[67,4983,3105],{},[67,4985,4986],{"class":69,"line":180},[67,4987,95],{"emptyLinePlaceholder":94},[67,4989,4990],{"class":69,"line":188},[67,4991,3114],{},[67,4993,4994],{"class":69,"line":196},[67,4995,3119],{},[67,4997,4998],{"class":69,"line":204},[67,4999,3124],{},[67,5001,5002],{"class":69,"line":212},[67,5003,3129],{},[67,5005,5006],{"class":69,"line":467},[67,5007,3134],{},[67,5009,5010],{"class":69,"line":497},[67,5011,3139],{},[67,5013,5014],{"class":69,"line":503},[67,5015,3144],{},[67,5017,5018],{"class":69,"line":521},[67,5019,95],{"emptyLinePlaceholder":94},[67,5021,5022],{"class":69,"line":528},[67,5023,3153],{},[67,5025,5026],{"class":69,"line":540},[67,5027,3158],{},[67,5029,5030],{"class":69,"line":557},[67,5031,95],{"emptyLinePlaceholder":94},[67,5033,5034],{"class":69,"line":562},[67,5035,3167],{},[67,5037,5038],{"class":69,"line":568},[67,5039,3172],{},[67,5041,5042],{"class":69,"line":1089},[67,5043,3177],{},[67,5045,5046],{"class":69,"line":1099},[67,5047,5048],{},"            hls_path \u002Fusr\u002Fshare\u002Fnginx\u002Fhtml\u002Fhls;\n",[67,5050,5051],{"class":69,"line":1302},[67,5052,3187],{},[67,5054,5055],{"class":69,"line":1308},[67,5056,565],{},[67,5058,5059],{"class":69,"line":1313},[67,5060,3201],{},[67,5062,5063],{"class":69,"line":1319},[67,5064,571],{},[67,5066,5067],{"class":69,"line":1324},[67,5068,95],{"emptyLinePlaceholder":94},[67,5070,5071],{"class":69,"line":1330},[67,5072,95],{"emptyLinePlaceholder":94},[67,5074,5075],{"class":69,"line":1335},[67,5076,95],{"emptyLinePlaceholder":94},[67,5078,5079],{"class":69,"line":1341},[67,5080,3222],{},[67,5082,5083],{"class":69,"line":1346},[67,5084,3227],{},[67,5086,5087],{"class":69,"line":1352},[67,5088,3232],{},[67,5090,5091],{"class":69,"line":1357},[67,5092,95],{"emptyLinePlaceholder":94},[67,5094,5095],{"class":69,"line":1363},[67,5096,3241],{},[67,5098,5099],{"class":69,"line":1368},[67,5100,3246],{},[67,5102,5103],{"class":69,"line":1374},[67,5104,3251],{},[67,5106,5107],{"class":69,"line":1379},[67,5108,95],{"emptyLinePlaceholder":94},[67,5110,5111],{"class":69,"line":1384},[67,5112,3260],{},[67,5114,5115],{"class":69,"line":1389},[67,5116,95],{"emptyLinePlaceholder":94},[67,5118,5119],{"class":69,"line":1395},[67,5120,3269],{},[67,5122,5123],{"class":69,"line":1400},[67,5124,3274],{},[67,5126,5127],{"class":69,"line":1406},[67,5128,95],{"emptyLinePlaceholder":94},[67,5130,5131],{"class":69,"line":1411},[67,5132,3284],{},[67,5134,5135],{"class":69,"line":3281},[67,5136,95],{"emptyLinePlaceholder":94},[67,5138,5139],{"class":69,"line":3287},[67,5140,3295],{},[67,5142,5143],{"class":69,"line":3292},[67,5144,95],{"emptyLinePlaceholder":94},[67,5146,5147],{"class":69,"line":3298},[67,5148,3306],{},[67,5150,5151],{"class":69,"line":3303},[67,5152,571],{},[13,5154,5155,5156,5159],{},"このファイルはコンテナ内の",[41,5157,5158],{},"nginx.conf","にボリュームします。tiangolo\u002Fnginx-rtmpのイメージで生成されるnginx.confはRTMPのために最低限の記述しかないので上記のようにします。",[13,5161,5162],{},"RTMPでは以下の設定です。",[34,5164,5166],{"className":3050,"code":5165,"language":3053,"meta":43,"style":43},"rtmp {\n    server {\n        listen 1935;\n        listen [::]:1935 ipv6only=on;\n        access_log \u002Fvar\u002Flog\u002Frtmp_access.log;\n        chunk_size 4096;\n        timeout 10s;\n\n        application live {\n            live on;\n\n            # HLSの記述欄\n            hls on;\n            # ここに映像ファイルが配置される\n            hls_path \u002Fusr\u002Fshare\u002Fnginx\u002Fhtml\u002Fhls;\n            hls_fragment 10s;\n        }\n    }\n}\n",[41,5167,5168,5172,5176,5180,5184,5188,5192,5196,5200,5204,5208,5212,5216,5220,5224,5228,5232,5236,5240],{"__ignoreMap":43},[67,5169,5170],{"class":69,"line":70},[67,5171,3114],{},[67,5173,5174],{"class":69,"line":91},[67,5175,3119],{},[67,5177,5178],{"class":69,"line":98},[67,5179,3124],{},[67,5181,5182],{"class":69,"line":107},[67,5183,3129],{},[67,5185,5186],{"class":69,"line":4},[67,5187,3134],{},[67,5189,5190],{"class":69,"line":125},[67,5191,3139],{},[67,5193,5194],{"class":69,"line":136},[67,5195,3144],{},[67,5197,5198],{"class":69,"line":144},[67,5199,95],{"emptyLinePlaceholder":94},[67,5201,5202],{"class":69,"line":153},[67,5203,3153],{},[67,5205,5206],{"class":69,"line":164},[67,5207,3158],{},[67,5209,5210],{"class":69,"line":172},[67,5211,95],{"emptyLinePlaceholder":94},[67,5213,5214],{"class":69,"line":180},[67,5215,3167],{},[67,5217,5218],{"class":69,"line":188},[67,5219,3172],{},[67,5221,5222],{"class":69,"line":196},[67,5223,3177],{},[67,5225,5226],{"class":69,"line":204},[67,5227,5048],{},[67,5229,5230],{"class":69,"line":212},[67,5231,3187],{},[67,5233,5234],{"class":69,"line":467},[67,5235,565],{},[67,5237,5238],{"class":69,"line":497},[67,5239,3201],{},[67,5241,5242],{"class":69,"line":503},[67,5243,571],{},[13,5245,5246,5247,5249],{},"ここでは1935ポートでRTMPをリッスンし、また",[41,5248,4772],{},"というURLでアップロードできるようにしています。",[2108,5251,1134],{"id":1134},[13,5253,5254,5255,5258],{},"webは以下のようにしておきます。ドキュメントルートは",[41,5256,5257],{},"\u002Fusr\u002Fshare\u002Fnginx\u002Fhtml","です。",[34,5260,5262],{"className":3050,"code":5261,"filename":3052,"language":3053,"meta":43,"style":43},"server {\n    listen       80;\n    listen  [::]:80;\n    server_name  localhost;\n\n    #access_log  \u002Fvar\u002Flog\u002Fnginx\u002Fhost.access.log  main;\n\n    location \u002F {\n        root   \u002Fusr\u002Fshare\u002Fnginx\u002Fhtml;\n        index  index.html index.htm;\n    }\n\n    #error_page  404              \u002F404.html;\n\n    # redirect server error pages to the static page \u002F50x.html\n    #\n    error_page   500 502 503 504  \u002F50x.html;\n    location = \u002F50x.html {\n        root   \u002Fusr\u002Fshare\u002Fnginx\u002Fhtml;\n    }\n\n    # proxy the PHP scripts to Apache listening on 127.0.0.1:80\n    #\n    #location ~ \\.php$ {\n    #    proxy_pass   http:\u002F\u002F127.0.0.1;\n    #}\n\n    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000\n    #\n    #location ~ \\.php$ {\n    #    root           html;\n    #    fastcgi_pass   127.0.0.1:9000;\n    #    fastcgi_index  index.php;\n    #    fastcgi_param  SCRIPT_FILENAME  \u002Fscripts$fastcgi_script_name;\n    #    include        fastcgi_params;\n    #}\n\n    # deny access to .htaccess files, if Apache's document root\n    # concurs with nginx's one\n    #\n    #location ~ \u002F\\.ht {\n    #    deny  all;\n    #}\n}\n",[41,5263,5264,5268,5272,5276,5280,5284,5288,5292,5296,5301,5305,5309,5313,5317,5321,5325,5329,5333,5337,5341,5345,5349,5353,5357,5361,5365,5369,5373,5377,5381,5385,5389,5393,5397,5401,5405,5409,5413,5417,5421,5425,5429,5433,5437],{"__ignoreMap":43},[67,5265,5266],{"class":69,"line":70},[67,5267,3324],{},[67,5269,5270],{"class":69,"line":91},[67,5271,3329],{},[67,5273,5274],{"class":69,"line":98},[67,5275,3334],{},[67,5277,5278],{"class":69,"line":107},[67,5279,3339],{},[67,5281,5282],{"class":69,"line":4},[67,5283,95],{"emptyLinePlaceholder":94},[67,5285,5286],{"class":69,"line":125},[67,5287,3348],{},[67,5289,5290],{"class":69,"line":136},[67,5291,95],{"emptyLinePlaceholder":94},[67,5293,5294],{"class":69,"line":144},[67,5295,3357],{},[67,5297,5298],{"class":69,"line":153},[67,5299,5300],{},"        root   \u002Fusr\u002Fshare\u002Fnginx\u002Fhtml;\n",[67,5302,5303],{"class":69,"line":164},[67,5304,3367],{},[67,5306,5307],{"class":69,"line":172},[67,5308,3201],{},[67,5310,5311],{"class":69,"line":180},[67,5312,95],{"emptyLinePlaceholder":94},[67,5314,5315],{"class":69,"line":188},[67,5316,3380],{},[67,5318,5319],{"class":69,"line":196},[67,5320,95],{"emptyLinePlaceholder":94},[67,5322,5323],{"class":69,"line":204},[67,5324,3389],{},[67,5326,5327],{"class":69,"line":212},[67,5328,3394],{},[67,5330,5331],{"class":69,"line":467},[67,5332,3399],{},[67,5334,5335],{"class":69,"line":497},[67,5336,3404],{},[67,5338,5339],{"class":69,"line":503},[67,5340,5300],{},[67,5342,5343],{"class":69,"line":521},[67,5344,3201],{},[67,5346,5347],{"class":69,"line":528},[67,5348,95],{"emptyLinePlaceholder":94},[67,5350,5351],{"class":69,"line":540},[67,5352,3421],{},[67,5354,5355],{"class":69,"line":557},[67,5356,3394],{},[67,5358,5359],{"class":69,"line":562},[67,5360,3430],{},[67,5362,5363],{"class":69,"line":568},[67,5364,3435],{},[67,5366,5367],{"class":69,"line":1089},[67,5368,3440],{},[67,5370,5371],{"class":69,"line":1099},[67,5372,95],{"emptyLinePlaceholder":94},[67,5374,5375],{"class":69,"line":1302},[67,5376,3449],{},[67,5378,5379],{"class":69,"line":1308},[67,5380,3394],{},[67,5382,5383],{"class":69,"line":1313},[67,5384,3430],{},[67,5386,5387],{"class":69,"line":1319},[67,5388,3462],{},[67,5390,5391],{"class":69,"line":1324},[67,5392,3467],{},[67,5394,5395],{"class":69,"line":1330},[67,5396,3472],{},[67,5398,5399],{"class":69,"line":1335},[67,5400,3477],{},[67,5402,5403],{"class":69,"line":1341},[67,5404,3482],{},[67,5406,5407],{"class":69,"line":1346},[67,5408,3440],{},[67,5410,5411],{"class":69,"line":1352},[67,5412,95],{"emptyLinePlaceholder":94},[67,5414,5415],{"class":69,"line":1357},[67,5416,3495],{},[67,5418,5419],{"class":69,"line":1363},[67,5420,3500],{},[67,5422,5423],{"class":69,"line":1368},[67,5424,3394],{},[67,5426,5427],{"class":69,"line":1374},[67,5428,3509],{},[67,5430,5431],{"class":69,"line":1379},[67,5432,3514],{},[67,5434,5435],{"class":69,"line":1384},[67,5436,3440],{},[67,5438,5439],{"class":69,"line":1389},[67,5440,571],{},[13,5442,5443],{},"RTMPを含むNginxの設定はこれでOKです。",[598,5445,5446],{"id":5446},"web側実装",[13,5448,5449,5452],{},[41,5450,5451],{},"html\u002Ftest.html","として以下のように作成します。",[34,5454,5457],{"className":3681,"code":5455,"filename":5456,"language":3684,"meta":43,"style":43},"\u003C!DOCTYPE html>\n\u003Chtml>\n\n\u003Chead>\n  \u003Cmeta charset=\"utf-8\">\n  \u003Ctitle>MediaElement\u003C\u002Ftitle>\n  \u003C!-- MediaElement style -->\n  \u003Clink rel=\"stylesheet\" href=\"\u002F\u002Fcdnjs.cloudflare.com\u002Fajax\u002Flibs\u002Fmediaelement\u002F4.2.9\u002Fmediaelementplayer.css\" \u002F>\n\u003C\u002Fhead>\n\n\u003Cbody>\n  \u003C!-- MediaElement -->\n  \u003Cscript src=\"\u002F\u002Fcdnjs.cloudflare.com\u002Fajax\u002Flibs\u002Fmediaelement\u002F4.2.9\u002Fmediaelement-and-player.js\">\u003C\u002Fscript>\n\n  \u003Cvideo id=\"player\" width=\"640\" height=\"360\">\n\u003C\u002Fbody>\n\u003Cscript type=\"text\u002Fjavascript\">\n\n      var player = new MediaElementPlayer('player', {\n        success: function(mediaElement, originalNode) {\n          console.log(\"Player initialised\");\n        }\n      });\n        player.setSrc(\"hls\u002F.m3u8\");\n\u003C\u002Fscript>\n\n\u003C\u002Fhtml>\n","test.html",[41,5458,5459,5469,5477,5481,5489,5507,5523,5527,5555,5563,5567,5575,5579,5601,5605,5643,5651,5669,5673,5697,5717,5737,5741,5749,5770,5778,5782],{"__ignoreMap":43},[67,5460,5461,5463,5465,5467],{"class":69,"line":70},[67,5462,3691],{"class":77},[67,5464,3694],{"class":73},[67,5466,3697],{"class":245},[67,5468,3700],{"class":77},[67,5470,5471,5473,5475],{"class":69,"line":91},[67,5472,3705],{"class":77},[67,5474,3684],{"class":73},[67,5476,3700],{"class":77},[67,5478,5479],{"class":69,"line":98},[67,5480,95],{"emptyLinePlaceholder":94},[67,5482,5483,5485,5487],{"class":69,"line":107},[67,5484,3705],{"class":77},[67,5486,3720],{"class":73},[67,5488,3700],{"class":77},[67,5490,5491,5493,5495,5497,5499,5501,5503,5505],{"class":69,"line":4},[67,5492,3727],{"class":77},[67,5494,3730],{"class":73},[67,5496,3733],{"class":245},[67,5498,253],{"class":77},[67,5500,314],{"class":77},[67,5502,3740],{"class":84},[67,5504,314],{"class":77},[67,5506,3700],{"class":77},[67,5508,5509,5511,5513,5515,5517,5519,5521],{"class":69,"line":125},[67,5510,3727],{"class":77},[67,5512,3751],{"class":73},[67,5514,3754],{"class":77},[67,5516,3757],{"class":249},[67,5518,3760],{"class":77},[67,5520,3751],{"class":73},[67,5522,3700],{"class":77},[67,5524,5525],{"class":69,"line":136},[67,5526,3769],{"class":751},[67,5528,5529,5531,5533,5535,5537,5539,5541,5543,5545,5547,5549,5551,5553],{"class":69,"line":144},[67,5530,3727],{"class":77},[67,5532,3776],{"class":73},[67,5534,3779],{"class":245},[67,5536,253],{"class":77},[67,5538,314],{"class":77},[67,5540,3786],{"class":84},[67,5542,314],{"class":77},[67,5544,3791],{"class":245},[67,5546,253],{"class":77},[67,5548,314],{"class":77},[67,5550,3798],{"class":84},[67,5552,314],{"class":77},[67,5554,3803],{"class":77},[67,5556,5557,5559,5561],{"class":69,"line":153},[67,5558,3760],{"class":77},[67,5560,3720],{"class":73},[67,5562,3700],{"class":77},[67,5564,5565],{"class":69,"line":164},[67,5566,95],{"emptyLinePlaceholder":94},[67,5568,5569,5571,5573],{"class":69,"line":172},[67,5570,3705],{"class":77},[67,5572,3822],{"class":73},[67,5574,3700],{"class":77},[67,5576,5577],{"class":69,"line":180},[67,5578,3829],{"class":751},[67,5580,5581,5583,5585,5587,5589,5591,5593,5595,5597,5599],{"class":69,"line":188},[67,5582,3727],{"class":77},[67,5584,3836],{"class":73},[67,5586,3839],{"class":245},[67,5588,253],{"class":77},[67,5590,314],{"class":77},[67,5592,3846],{"class":84},[67,5594,314],{"class":77},[67,5596,3851],{"class":77},[67,5598,3836],{"class":73},[67,5600,3700],{"class":77},[67,5602,5603],{"class":69,"line":196},[67,5604,95],{"emptyLinePlaceholder":94},[67,5606,5607,5609,5611,5613,5615,5617,5619,5621,5623,5625,5627,5629,5631,5633,5635,5637,5639,5641],{"class":69,"line":204},[67,5608,3727],{"class":77},[67,5610,3866],{"class":73},[67,5612,3869],{"class":245},[67,5614,253],{"class":77},[67,5616,314],{"class":77},[67,5618,3876],{"class":84},[67,5620,314],{"class":77},[67,5622,3881],{"class":245},[67,5624,253],{"class":77},[67,5626,314],{"class":77},[67,5628,3888],{"class":84},[67,5630,314],{"class":77},[67,5632,3893],{"class":245},[67,5634,253],{"class":77},[67,5636,314],{"class":77},[67,5638,3900],{"class":84},[67,5640,314],{"class":77},[67,5642,3700],{"class":77},[67,5644,5645,5647,5649],{"class":69,"line":212},[67,5646,3760],{"class":77},[67,5648,3822],{"class":73},[67,5650,3700],{"class":77},[67,5652,5653,5655,5657,5659,5661,5663,5665,5667],{"class":69,"line":467},[67,5654,3705],{"class":77},[67,5656,3836],{"class":73},[67,5658,3921],{"class":245},[67,5660,253],{"class":77},[67,5662,314],{"class":77},[67,5664,3928],{"class":84},[67,5666,314],{"class":77},[67,5668,3700],{"class":77},[67,5670,5671],{"class":69,"line":497},[67,5672,95],{"emptyLinePlaceholder":94},[67,5674,5675,5677,5679,5681,5683,5685,5687,5689,5691,5693,5695],{"class":69,"line":503},[67,5676,3941],{"class":245},[67,5678,3944],{"class":249},[67,5680,253],{"class":77},[67,5682,3949],{"class":77},[67,5684,3952],{"class":256},[67,5686,260],{"class":249},[67,5688,263],{"class":77},[67,5690,3876],{"class":84},[67,5692,263],{"class":77},[67,5694,350],{"class":77},[67,5696,299],{"class":77},[67,5698,5699,5701,5703,5705,5707,5709,5711,5713,5715],{"class":69,"line":521},[67,5700,3969],{"class":256},[67,5702,78],{"class":77},[67,5704,3974],{"class":245},[67,5706,260],{"class":77},[67,5708,3979],{"class":346},[67,5710,350],{"class":77},[67,5712,3984],{"class":346},[67,5714,356],{"class":77},[67,5716,299],{"class":77},[67,5718,5719,5721,5723,5725,5727,5729,5731,5733,5735],{"class":69,"line":528},[67,5720,3993],{"class":249},[67,5722,426],{"class":77},[67,5724,3998],{"class":256},[67,5726,260],{"class":73},[67,5728,314],{"class":77},[67,5730,4005],{"class":84},[67,5732,314],{"class":77},[67,5734,356],{"class":73},[67,5736,282],{"class":77},[67,5738,5739],{"class":69,"line":540},[67,5740,565],{"class":77},[67,5742,5743,5745,5747],{"class":69,"line":557},[67,5744,4020],{"class":77},[67,5746,356],{"class":249},[67,5748,282],{"class":77},[67,5750,5751,5753,5755,5757,5759,5761,5764,5766,5768],{"class":69,"line":562},[67,5752,4029],{"class":249},[67,5754,426],{"class":77},[67,5756,4034],{"class":256},[67,5758,260],{"class":249},[67,5760,314],{"class":77},[67,5762,5763],{"class":84},"hls\u002F.m3u8",[67,5765,314],{"class":77},[67,5767,356],{"class":249},[67,5769,282],{"class":77},[67,5771,5772,5774,5776],{"class":69,"line":568},[67,5773,3760],{"class":77},[67,5775,3836],{"class":73},[67,5777,3700],{"class":77},[67,5779,5780],{"class":69,"line":1089},[67,5781,95],{"emptyLinePlaceholder":94},[67,5783,5784,5786,5788],{"class":69,"line":1099},[67,5785,3760],{"class":77},[67,5787,3684],{"class":73},[67,5789,3700],{"class":77},[13,5791,5792,5793,5795],{},"hlsが再生できるようにjsの再生ライブラリを用意します。",[41,5794,5763],{},"については後述します。",[598,5797,5798],{"id":5798},"dokcer起動",[34,5800,5803],{"className":5801,"code":5802,"language":39},[37],"docker-compose up -d\n",[41,5804,5802],{"__ignoreMap":43},[13,5806,5807],{},"を用いてdockerイメージを起動しましょう。",[51,5809,5811],{"id":5810},"配信テスト","配信テスト！",[598,5813,5815],{"id":5814},"macのipを確認","MacのIPを確認",[13,5817,5818],{},"今回のはMac上にRTMPサーバを立てたのでMacのIPを確認しておきます。「システム環境設定」から「ネットワーク」を選択し、Wi-FiからIPアドレスを確認します。このPCは「192.168.0.3」なので",[13,5820,5821,5822,5825,5826,5829],{},"RTMPは",[41,5823,5824],{},"rtmp:\u002F\u002F192.168.0.3\u002Flive","、webは",[41,5827,5828],{},"http:\u002F\u002F192.168.0.3\u002Findex.html","でアクセスできます。",[2463,5831],{":src":5832,":width":2466},"'rtmp-docker-local\u002Fmac.png'",[598,5834,5835],{"id":5835},"gopro側の設定",[13,5837,5838],{},"Goproとアプリのテザリングなどは省略します。",[13,5840,5841,5846],{},[23,5842,5845],{"href":5843,"rel":5844},"https:\u002F\u002Fapps.apple.com\u002Fjp\u002Fapp\u002Fgopro-quik-%E5%8B%95%E7%94%BB-%E5%86%99%E7%9C%9F%E7%B7%A8%E9%9B%86%E3%82%A2%E3%83%97%E3%83%AA\u002Fid561350520",[27],"公式アプリ（app store）",[23,5847,5850],{"href":5848,"rel":5849},"https:\u002F\u002Fplay.google.com\u002Fstore\u002Fapps\u002Fdetails?id=com.gopro.smarty&hl=ja&gl=US",[27],"公式アプリ（android）",[13,5852,5853,5854],{},"goproとアプリを接続して、「ライブの設定」に移動\n",[2463,5855],{":src":5856,":width":5857,":center":4356},"'rtmp-docker-local\u002Fg1.jpg'","'200px'",[13,5859,5860,5861],{},"その他、RTMPを選択\n",[2463,5862],{":src":5863,":width":5857,":center":4356},"'rtmp-docker-local\u002Fg2.jpg'",[13,5865,5866,5867,5869,5870],{},"Macと同じwi-fiに接続して",[41,5868,5824],{},"をURLに入力\n",[2463,5871],{":src":5872,":width":5857,":center":4356},"'rtmp-docker-local\u002Fg3.jpg'",[13,5874,5875],{},"設定が完了したらライブ配信を開始します。",[598,5877,5878],{"id":5878},"サーバーでは",[13,5880,5881],{},"ライブ配信を開始するとRTMPのURLへ動画がアップされていきます。サーバーの方ではドキュメントルートにこの映像のHLSが配置されるようにしたので、マウントの関係上以下のようなディレクトリが発生していると思います。",[2463,5883],{":src":5884,":width":5885,":center":4356},"'rtmp-docker-local\u002Fserver.png'","'100px'",[13,5887,5888,5889,5891],{},"先程のHTMLにあった「",[41,5890,5763],{},"」はサーバーにアップロードされた映像の元でもあるファイルを示しています。",[598,5893,5895],{"id":5894},"ブラウザを見てみると","ブラウザを見てみると..",[13,5897,5898,5899,5902],{},"では",[41,5900,5901],{},"http:\u002F\u002Flocalhost:8085\u002Findex.html","でPCから映像を見てみましょう。再生ボタンを押すと以下のようになりました。",[2463,5904],{":src":5905,":width":2466},"'rtmp-docker-local\u002Fweb.png'",[13,5907,5908],{},"しっかりとGoproが写している映像が表示され、音声も流れました。画面を写していましたが、いろいろカメラを回すと確かに映像・音声も切り替わります。",[13,5910,5911],{},"とりあえずこれでライブ配信映像を自前で実装したサーバに送ることが確認できました。今度はサーバー内での映像をyoutubeのlivestreaming apiなどを通じて実際にライブ映像に流せるようにしてみます。",[51,5913,5914],{"id":5914},"参考",[13,5916,5917],{},"今回参考にした資料です。非常に助かりました。",[1112,5919,5920,5927,5934],{},[1115,5921,5922],{},[23,5923,5926],{"href":5924,"rel":5925},"https:\u002F\u002Fqiita.com\u002Fkobakazu0429\u002Fitems\u002F33739b83000583c5448e",[27],"docker-nginx-rtmpとiPhoneでお手軽マルチカメラライブストリーミング配信環境の構築",[1115,5928,5929],{},[23,5930,5933],{"href":5931,"rel":5932},"https:\u002F\u002Fblog.litus.co.jp\u002F2020\u002F11\u002Fdockerhlswebcentos-nginxffmpegdocker.html",[27],"Dockerコンテナ化させたHLSのwebストリーミング配信環境構築",[1115,5935,5936],{},[23,5937,5939],{"href":4822,"rel":5938},[27],"Docker image",[809,5941,4616],{},{"title":43,"searchDepth":98,"depth":98,"links":5943},[5944,5949,5953,5962,5968],{"id":4668,"depth":91,"text":4668,"children":5945},[5946,5947,5948],{"id":4685,"depth":98,"text":4685},{"id":4679,"depth":98,"text":4679},{"id":4715,"depth":98,"text":4715},{"id":4727,"depth":91,"text":4727,"children":5950},[5951,5952],{"id":4758,"depth":98,"text":4759},{"id":4765,"depth":98,"text":4766},{"id":4776,"depth":91,"text":4777,"children":5954},[5955,5956,5960,5961],{"id":4780,"depth":98,"text":4780},{"id":4925,"depth":98,"text":4925,"children":5957},[5958,5959],{"id":2779,"depth":107,"text":4931},{"id":1134,"depth":107,"text":1134},{"id":5446,"depth":98,"text":5446},{"id":5798,"depth":98,"text":5798},{"id":5810,"depth":91,"text":5811,"children":5963},[5964,5965,5966,5967],{"id":5814,"depth":98,"text":5815},{"id":5835,"depth":98,"text":5835},{"id":5878,"depth":98,"text":5878},{"id":5894,"depth":98,"text":5895},{"id":5914,"depth":91,"text":5914},[2651],"2022-05-20","ローカルのDockerとNginxを用いてGoproからライブ配信映像をRTMPを再生する",{},"\u002Fseries\u002Frtmp-manager-server-1",{"title":4653,"description":5971},"series\u002Frtmp-manager-server-1",[831,4648],"rtmp-docker-local\u002Fthumbnail.png","_e2Aj1JaZSf-KJSGe6AqjuPlf5YdLmKDjuCXzhFw0dg",{"id":5980,"title":5981,"body":5982,"category":6508,"createdAt":6509,"description":5981,"extension":823,"index":824,"meta":6510,"navigation":94,"path":1508,"publish":94,"seo":6511,"series":824,"seriesTitle":824,"stem":6512,"tag":6513,"thumbnail":824,"updatedAt":824,"__hash__":6515},"articles\u002Farticles\u002Fstuck-on-docker-centos8.md","Docker でcentos8+Apache2.4 の環境を作ろうとして詰まった",{"type":10,"value":5983,"toc":6504},[5984,5987,5995,5998,6001,6009,6013,6016,6106,6109,6136,6139,6165,6171,6279,6286,6290,6296,6302,6305,6448,6451,6482,6492,6501],[13,5985,5986],{},"この記事はosからイメージを指定して作ろうとして、FROM centos から構築して",[13,5988,5989,5992],{},[41,5990,5991],{},"Failed to connect to bus: No such file or directory docker",[41,5993,5994],{},"System has not been booted with systemd as init system (PID 1). Can't operate. Failed to connect to bus: Host is down",[13,5996,5997],{},"というエラーで詰まってブチ切れそうになっている人は以下の方法を確認してみてください。原因は「公式に解決法がありました」から述べていきます。",[13,5999,6000],{},"この記事で使用したOSとdockerのバージョン",[1112,6002,6003,6006],{},[1115,6004,6005],{},"docker：19.03.13",[1115,6007,6008],{},"maxOS Catalina 10.15.5",[51,6010,6012],{"id":6011},"dockerfileからcentos8apache24の環境作ろうとした","Dockerfileからcentos8+apache2.4の環境作ろうとした",[13,6014,6015],{},"apacheのイメージを入れるとosがUbuntuだったりで、できたらosから指定したいなーと思ってcenots8の環境にapacheを入れて行こうと思い以下のようにDockerfileを記述",[34,6017,6019],{"className":1168,"code":6018,"filename":1138,"language":1170,"meta":43,"style":43},"FROM centos:8\n\nRUN \u002Fbin\u002Fcp \u002Fusr\u002Fshare\u002Fzoneinfo\u002FAsia\u002FTokyo \u002Fetc\u002Flocaltime\n\nRUN yum install -y epel-release && yum clean all\n\nRUN rpm -ivh http:\u002F\u002Fftp.riken.jp\u002FLinux\u002Fremi\u002Fenterprise\u002Fremi-release-8.rpm\n\nRUN yum -y update && yum clean all\n\nRUN yum -y install httpd && yum clean all\n\nRUN yum -y install php74-php php74-php-mysqli php74-php-gd php74-php-mbstring php74-php-opcache php74-php-xml php74-php-pear php74-php-devel php74-php-pecl-imagick php74-php-pecl-imagick-devel php74-php-pecl-zip\n\nRUN ln \u002Fusr\u002Fbin\u002Fphp74 \u002Fusr\u002Fbin\u002Fphp\n\nRUN chown -R apache:apache \u002Fvar\u002Fwww\u002Fhtml\n\nRUN systemctl enable php74-php-fpm\n\nRUN systemctl enable httpd \n",[41,6020,6021,6025,6029,6033,6037,6041,6045,6049,6053,6057,6061,6065,6069,6073,6077,6081,6085,6089,6093,6097,6101],{"__ignoreMap":43},[67,6022,6023],{"class":69,"line":70},[67,6024,1177],{},[67,6026,6027],{"class":69,"line":91},[67,6028,95],{"emptyLinePlaceholder":94},[67,6030,6031],{"class":69,"line":98},[67,6032,1250],{},[67,6034,6035],{"class":69,"line":107},[67,6036,95],{"emptyLinePlaceholder":94},[67,6038,6039],{"class":69,"line":4},[67,6040,1259],{},[67,6042,6043],{"class":69,"line":125},[67,6044,95],{"emptyLinePlaceholder":94},[67,6046,6047],{"class":69,"line":136},[67,6048,1268],{},[67,6050,6051],{"class":69,"line":144},[67,6052,95],{"emptyLinePlaceholder":94},[67,6054,6055],{"class":69,"line":153},[67,6056,1277],{},[67,6058,6059],{"class":69,"line":164},[67,6060,95],{"emptyLinePlaceholder":94},[67,6062,6063],{"class":69,"line":172},[67,6064,1286],{},[67,6066,6067],{"class":69,"line":180},[67,6068,95],{"emptyLinePlaceholder":94},[67,6070,6071],{"class":69,"line":188},[67,6072,1305],{},[67,6074,6075],{"class":69,"line":196},[67,6076,95],{"emptyLinePlaceholder":94},[67,6078,6079],{"class":69,"line":204},[67,6080,1316],{},[67,6082,6083],{"class":69,"line":212},[67,6084,95],{"emptyLinePlaceholder":94},[67,6086,6087],{"class":69,"line":467},[67,6088,1338],{},[67,6090,6091],{"class":69,"line":497},[67,6092,95],{"emptyLinePlaceholder":94},[67,6094,6095],{"class":69,"line":503},[67,6096,1349],{},[67,6098,6099],{"class":69,"line":521},[67,6100,95],{"emptyLinePlaceholder":94},[67,6102,6103],{"class":69,"line":528},[67,6104,6105],{},"RUN systemctl enable httpd\n",[13,6107,6108],{},"php入っていますがとりあえず上のような感じで必要なものを入れて、apacheを常にONにすれば行けるだろ思い、ビルドする",[34,6110,6114],{"className":6111,"code":6112,"language":6113,"meta":43,"style":43},"language-bash shiki shiki-themes material-theme-ocean","$ docker build -t centos_apche:1.0 .\n","bash",[41,6115,6116],{"__ignoreMap":43},[67,6117,6118,6122,6125,6128,6131,6134],{"class":69,"line":70},[67,6119,6121],{"class":6120},"s5Dmg","$",[67,6123,6124],{"class":84}," docker",[67,6126,6127],{"class":84}," build",[67,6129,6130],{"class":84}," -t",[67,6132,6133],{"class":84}," centos_apche:1.0",[67,6135,2948],{"class":84},[13,6137,6138],{},"ビルドは普通に成功しました。イメージが作られたのを確認していざコンテナを起動。",[34,6140,6142],{"className":6111,"code":6141,"language":6113,"meta":43,"style":43},"docker run -t -d -p 9000:80 centos_apche:1.0\n",[41,6143,6144],{"__ignoreMap":43},[67,6145,6146,6148,6151,6153,6156,6159,6162],{"class":69,"line":70},[67,6147,831],{"class":6120},[67,6149,6150],{"class":84}," run",[67,6152,6130],{"class":84},[67,6154,6155],{"class":84}," -d",[67,6157,6158],{"class":84}," -p",[67,6160,6161],{"class":84}," 9000:80",[67,6163,6164],{"class":84}," centos_apche:1.0\n",[13,6166,6167,6168,6170],{},"しかし localhost:9000 にアクセスすると「データが送信されませんでした」と真っ黒（chrome）。",[41,6169,2449],{}," で稼働状態を調べてもコンテナはきちんと動いている。つまりコンテナの中で何か起きている。",[34,6172,6174],{"className":6111,"code":6173,"language":6113,"meta":43,"style":43},"docker exec -it {container_id or name} \u002Fbin\u002Fbash\n...\n[root@32212888398b \u002F]# \n[root@32212888398b \u002F]# systemctl httpd status \nSystem has not been booted with systemd as init system (PID 1). Can't operate. \nFailed to connect to bus: Host is down\n",[41,6175,6176,6198,6203,6217,6228,6274],{"__ignoreMap":43},[67,6177,6178,6180,6183,6186,6189,6192,6195],{"class":69,"line":70},[67,6179,831],{"class":6120},[67,6181,6182],{"class":84}," exec",[67,6184,6185],{"class":84}," -it",[67,6187,6188],{"class":84}," {container_id",[67,6190,6191],{"class":84}," or",[67,6193,6194],{"class":84}," name}",[67,6196,6197],{"class":84}," \u002Fbin\u002Fbash\n",[67,6199,6200],{"class":69,"line":91},[67,6201,6202],{"class":256},"...\n",[67,6204,6205,6208,6211,6214],{"class":69,"line":98},[67,6206,6207],{"class":77},"[",[67,6209,6210],{"class":249},"root@32212888398b \u002F",[67,6212,6213],{"class":77},"]",[67,6215,6216],{"class":249},"# \n",[67,6218,6219,6221,6223,6225],{"class":69,"line":107},[67,6220,6207],{"class":77},[67,6222,6210],{"class":249},[67,6224,6213],{"class":77},[67,6226,6227],{"class":249},"# systemctl httpd status \n",[67,6229,6230,6233,6236,6239,6242,6245,6248,6251,6254,6257,6260,6263,6266,6269,6271],{"class":69,"line":4},[67,6231,6232],{"class":6120},"System",[67,6234,6235],{"class":84}," has",[67,6237,6238],{"class":84}," not",[67,6240,6241],{"class":84}," been",[67,6243,6244],{"class":84}," booted",[67,6246,6247],{"class":84}," with",[67,6249,6250],{"class":84}," systemd",[67,6252,6253],{"class":84}," as",[67,6255,6256],{"class":84}," init",[67,6258,6259],{"class":84}," system",[67,6261,6262],{"class":249}," (PID ",[67,6264,6265],{"class":461},"1",[67,6267,6268],{"class":249},"). Can",[67,6270,263],{"class":77},[67,6272,6273],{"class":84},"t operate. \n",[67,6275,6276],{"class":69,"line":125},[67,6277,6278],{"class":84},"Failed to connect to bus: Host is down\n",[13,6280,6281,6282,6285],{},"「は？」とりあえずhttpdが動いていないそうな上に「Host is down」とos自体がダメと言うことか？",[41,6283,6284],{},"systemctl","だけ打ってもエラーしか出ない。",[51,6287,6289],{"id":6288},"公式に解決法がありました","公式に解決法がありました。",[13,6291,6292,6293,6295],{},"いろいろ調べましたが ",[41,6294,2162],{}," を起動する方法がcentos7、centos:latest（つまり８）ではデフォルトでアクティブにならず一工夫必要だそうです。",[13,6297,6298],{},[23,6299,6301],{"href":1499,"rel":6300},[27],"公式ドキュメント",[13,6303,6304],{},"私も詳しい仕組みまではわからないのですが、まずDockerfileを以下のように追記します。",[34,6306,6308],{"className":1168,"code":6307,"filename":1138,"language":1170,"meta":43,"style":43},"FROM centos:8\n#ここから\nENV container docker\nRUN (cd \u002Flib\u002Fsystemd\u002Fsystem\u002Fsysinit.target.wants\u002F; for i in *; do [ $i == \\\nsystemd-tmpfiles-setup.service ] || rm -f $i; done); \\\nrm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Fmulti-user.target.wants\u002F*;\\\nrm -f \u002Fetc\u002Fsystemd\u002Fsystem\u002F*.wants\u002F*;\\\nrm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Flocal-fs.target.wants\u002F*; \\\nrm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Fsockets.target.wants\u002F*udev*; \\\nrm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Fsockets.target.wants\u002F*initctl*; \\\nrm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Fbasic.target.wants\u002F*;\\\nrm -f \u002Flib\u002Fsystemd\u002Fsystem\u002Fanaconda.target.wants\u002F*;\nVOLUME [ \"\u002Fsys\u002Ffs\u002Fcgroup\" ]\nCMD [\"\u002Fusr\u002Fsbin\u002Finit\"]\n#ここまで\nRUN \u002Fbin\u002Fcp \u002Fusr\u002Fshare\u002Fzoneinfo\u002FAsia\u002FTokyo \u002Fetc\u002Flocaltime\n\nRUN yum install -y epel-release && yum clean all\n\nRUN rpm -ivh http:\u002F\u002Fftp.riken.jp\u002FLinux\u002Fremi\u002Fenterprise\u002Fremi-release-8.rpm\n\nRUN yum -y update && yum clean all\n\nRUN yum -y install httpd && yum clean all\n\nRUN yum -y install php74-php php74-php-mysqli php74-php-gd php74-php-mbstring php74-php-opcache php74-php-xml php74-php-pear php74-php-devel php74-php-pecl-imagick php74-php-pecl-imagick-devel php74-php-pecl-zip\n\nRUN ln \u002Fusr\u002Fbin\u002Fphp74 \u002Fusr\u002Fbin\u002Fphp\n\nRUN chown -R apache:apache \u002Fvar\u002Fwww\u002Fhtml\n\nRUN systemctl enable php74-php-fpm\n\nRUN systemctl enable httpd \n",[41,6309,6310,6314,6319,6323,6327,6331,6335,6339,6343,6347,6351,6355,6359,6363,6367,6372,6376,6380,6384,6388,6392,6396,6400,6404,6408,6412,6416,6420,6424,6428,6432,6436,6440,6444],{"__ignoreMap":43},[67,6311,6312],{"class":69,"line":70},[67,6313,1177],{},[67,6315,6316],{"class":69,"line":91},[67,6317,6318],{},"#ここから\n",[67,6320,6321],{"class":69,"line":98},[67,6322,1186],{},[67,6324,6325],{"class":69,"line":107},[67,6326,1191],{},[67,6328,6329],{"class":69,"line":4},[67,6330,1196],{},[67,6332,6333],{"class":69,"line":125},[67,6334,1201],{},[67,6336,6337],{"class":69,"line":136},[67,6338,1206],{},[67,6340,6341],{"class":69,"line":144},[67,6342,1211],{},[67,6344,6345],{"class":69,"line":153},[67,6346,1216],{},[67,6348,6349],{"class":69,"line":164},[67,6350,1221],{},[67,6352,6353],{"class":69,"line":172},[67,6354,1226],{},[67,6356,6357],{"class":69,"line":180},[67,6358,1231],{},[67,6360,6361],{"class":69,"line":188},[67,6362,1236],{},[67,6364,6365],{"class":69,"line":196},[67,6366,1241],{},[67,6368,6369],{"class":69,"line":204},[67,6370,6371],{},"#ここまで\n",[67,6373,6374],{"class":69,"line":212},[67,6375,1250],{},[67,6377,6378],{"class":69,"line":467},[67,6379,95],{"emptyLinePlaceholder":94},[67,6381,6382],{"class":69,"line":497},[67,6383,1259],{},[67,6385,6386],{"class":69,"line":503},[67,6387,95],{"emptyLinePlaceholder":94},[67,6389,6390],{"class":69,"line":521},[67,6391,1268],{},[67,6393,6394],{"class":69,"line":528},[67,6395,95],{"emptyLinePlaceholder":94},[67,6397,6398],{"class":69,"line":540},[67,6399,1277],{},[67,6401,6402],{"class":69,"line":557},[67,6403,95],{"emptyLinePlaceholder":94},[67,6405,6406],{"class":69,"line":562},[67,6407,1286],{},[67,6409,6410],{"class":69,"line":568},[67,6411,95],{"emptyLinePlaceholder":94},[67,6413,6414],{"class":69,"line":1089},[67,6415,1305],{},[67,6417,6418],{"class":69,"line":1099},[67,6419,95],{"emptyLinePlaceholder":94},[67,6421,6422],{"class":69,"line":1302},[67,6423,1316],{},[67,6425,6426],{"class":69,"line":1308},[67,6427,95],{"emptyLinePlaceholder":94},[67,6429,6430],{"class":69,"line":1313},[67,6431,1338],{},[67,6433,6434],{"class":69,"line":1319},[67,6435,95],{"emptyLinePlaceholder":94},[67,6437,6438],{"class":69,"line":1324},[67,6439,1349],{},[67,6441,6442],{"class":69,"line":1330},[67,6443,95],{"emptyLinePlaceholder":94},[67,6445,6446],{"class":69,"line":1335},[67,6447,6105],{},[13,6449,6450],{},"そしてビルドは普通に行い、コンテナを立ち上げる際はボリュームともう一つオプションを指定します。",[34,6452,6454],{"className":6111,"code":6453,"language":6113,"meta":43,"style":43},"docker run -v \u002Fsys\u002Ffs\u002Fcgroup:\u002Fsys\u002Ffs\u002Fcgroup:ro --privileged -t -d -p 9000:80 centos_apched:1.0\n",[41,6455,6456],{"__ignoreMap":43},[67,6457,6458,6460,6462,6465,6468,6471,6473,6475,6477,6479],{"class":69,"line":70},[67,6459,831],{"class":6120},[67,6461,6150],{"class":84},[67,6463,6464],{"class":84}," -v",[67,6466,6467],{"class":84}," \u002Fsys\u002Ffs\u002Fcgroup:\u002Fsys\u002Ffs\u002Fcgroup:ro",[67,6469,6470],{"class":84}," --privileged",[67,6472,6130],{"class":84},[67,6474,6155],{"class":84},[67,6476,6158],{"class":84},[67,6478,6161],{"class":84},[67,6480,6481],{"class":84}," centos_apched:1.0\n",[13,6483,6484,6487,6488,6491],{},[41,6485,6486],{},"-v \u002Fsys\u002Ffs\u002Fcgroup:\u002Fsys\u002Ffs\u002Fcgroup:ro","でファイルシステムをホストマシンからボリュームし、",[41,6489,6490],{},"--privileged","でコンテナにホストマシンのroot権限を与ます。どちらか片方が抜けてもいけません。",[13,6493,6494,6495,6497,6498,6500],{},"このオプションとボリュームを指定すると",[41,6496,2162],{},"が動きます。実際にコンテナに入っていくと",[41,6499,6284],{},"コマンドが実行されました。",[809,6502,6503],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s5Dmg, html code.shiki .s5Dmg{--shiki-default:#FFCB6B}html pre.shiki code .sfyAc, html code.shiki .sfyAc{--shiki-default:#C3E88D}html pre.shiki code .sdLwU, html code.shiki .sdLwU{--shiki-default:#82AAFF}html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .s0W1g, html code.shiki .s0W1g{--shiki-default:#BABED8}html pre.shiki code .sx098, html code.shiki .sx098{--shiki-default:#F78C6C}",{"title":43,"searchDepth":98,"depth":98,"links":6505},[6506,6507],{"id":6011,"depth":91,"text":6012},{"id":6288,"depth":91,"text":6289},[2651],"2020-11-27",{},{"title":5981,"description":5981},"articles\u002Fstuck-on-docker-centos8",[6514,831],"infrastructure","yvD5JRk2N7X9ToHbPIm-hQQm0dyCSLPsVEnjEF9H-RE",1780987149872]