[{"data":1,"prerenderedAt":750},["ShallowReactive",2],{"navigation":3,"/docs/customizing-the-image/understanding-file-permissions":249,"/docs/customizing-the-image/understanding-file-permissions-surround":745},[4],{"title":5,"path":6,"stem":7,"children":8},"Docs","/docs","docs",[9,12,48,77,132,160,185,206,219,236],{"title":10,"path":6,"stem":11},"","docs/index",{"title":13,"path":14,"stem":15,"children":16,"icon":47},"Getting Started","/docs/getting-started","docs/1.getting-started/1.index",[17,19,23,27,31,35,39,43],{"title":18,"path":14,"stem":15},"Introduction",{"title":20,"path":21,"stem":22},"Container basics","/docs/getting-started/container-basics","docs/1.getting-started/2.container-basics",{"title":24,"path":25,"stem":26},"Installation","/docs/getting-started/installation","docs/1.getting-started/3.installation",{"title":28,"path":29,"stem":30},"These images vs others","/docs/getting-started/these-images-vs-others","docs/1.getting-started/4.these-images-vs-others",{"title":32,"path":33,"stem":34},"Choosing an image","/docs/getting-started/choosing-an-image","docs/1.getting-started/5.choosing-an-image",{"title":36,"path":37,"stem":38},"Default configurations","/docs/getting-started/default-configurations","docs/1.getting-started/6.default-configurations",{"title":40,"path":41,"stem":42},"Migrating from official PHP images","/docs/getting-started/migrating-from-official-php-images","docs/1.getting-started/7.migrating-from-official-php-images",{"title":44,"path":45,"stem":46},"Contributing","/docs/getting-started/contributing","docs/1.getting-started/99.contributing",false,{"title":49,"path":50,"stem":51,"children":52,"page":47},"Image Variations","/docs/image-variations","docs/2.image-variations",[53,57,61,65,69,73],{"title":54,"path":55,"stem":56},"CLI","/docs/image-variations/cli","docs/2.image-variations/cli",{"title":58,"path":59,"stem":60},"FPM","/docs/image-variations/fpm","docs/2.image-variations/fpm",{"title":62,"path":63,"stem":64},"FPM-Apache","/docs/image-variations/fpm-apache","docs/2.image-variations/fpm-apache",{"title":66,"path":67,"stem":68},"FPM-NGINX","/docs/image-variations/fpm-nginx","docs/2.image-variations/fpm-nginx",{"title":70,"path":71,"stem":72},"FrankenPHP","/docs/image-variations/frankenphp","docs/2.image-variations/frankenphp",{"title":74,"path":75,"stem":76},"NGINX Unit (removed)","/docs/image-variations/unit","docs/2.image-variations/unit",{"title":78,"path":79,"stem":80,"children":81,"page":47},"Framework Guides","/docs/framework-guides","docs/3.framework-guides",[82,123],{"title":83,"icon":47,"defaultOpen":47,"path":84,"stem":85,"children":86,"page":47},"Laravel","/docs/framework-guides/laravel","docs/3.framework-guides/1.laravel",[87,91,95,99,103,107,111,115,119],{"title":88,"path":89,"stem":90},"Automations","/docs/framework-guides/laravel/automations","docs/3.framework-guides/1.laravel/1.automations",{"title":92,"path":93,"stem":94},"Running workers","/docs/framework-guides/laravel/workers","docs/3.framework-guides/1.laravel/2.workers",{"title":96,"path":97,"stem":98},"Health checks","/docs/framework-guides/laravel/health-checks","docs/3.framework-guides/1.laravel/3.health-checks",{"title":100,"path":101,"stem":102},"Horizon","/docs/framework-guides/laravel/horizon","docs/3.framework-guides/1.laravel/4.horizon",{"title":104,"path":105,"stem":106},"Nightwatch","/docs/framework-guides/laravel/nightwatch","docs/3.framework-guides/1.laravel/5.nightwatch",{"title":108,"path":109,"stem":110},"Octane","/docs/framework-guides/laravel/octane","docs/3.framework-guides/1.laravel/6.octane",{"title":112,"path":113,"stem":114},"Queue","/docs/framework-guides/laravel/queue","docs/3.framework-guides/1.laravel/7.queue",{"title":116,"path":117,"stem":118},"Reverb","/docs/framework-guides/laravel/reverb","docs/3.framework-guides/1.laravel/8.reverb",{"title":120,"path":121,"stem":122},"Task scheduler","/docs/framework-guides/laravel/task-scheduler","docs/3.framework-guides/1.laravel/9.task-scheduler",{"title":124,"icon":47,"defaultOpen":47,"path":125,"stem":126,"children":127,"page":47},"WordPress","/docs/framework-guides/wordpress","docs/3.framework-guides/2.wordpress",[128],{"title":129,"path":130,"stem":131},"Using WordPress with Docker","/docs/framework-guides/wordpress/using-wordpress-with-docker","docs/3.framework-guides/2.wordpress/4.using-wordpress-with-docker",{"title":133,"path":134,"stem":135,"children":136,"page":47},"Deployment And Production","/docs/deployment-and-production","docs/4.deployment-and-production",[137,141,145,148,152,156],{"title":138,"path":139,"stem":140},"Packaging your app for deployment","/docs/deployment-and-production/packaging-your-app-for-deployment","docs/4.deployment-and-production/1.packaging-your-app-for-deployment",{"title":142,"path":143,"stem":144},"Configuring SSL","/docs/deployment-and-production/configuring-ssl","docs/4.deployment-and-production/2.configuring-ssl",{"title":96,"path":146,"stem":147},"/docs/deployment-and-production/health-checks","docs/4.deployment-and-production/3.health-checks",{"title":149,"path":150,"stem":151},"Configuring trusted proxies","/docs/deployment-and-production/configuring-trusted-proxies","docs/4.deployment-and-production/4.configuring-trusted-proxies",{"title":153,"path":154,"stem":155},"Production performance tuning","/docs/deployment-and-production/production-performance-tuning","docs/4.deployment-and-production/5.production-performance-tuning",{"title":157,"path":158,"stem":159},"Choosing a host","/docs/deployment-and-production/choosing-a-host","docs/4.deployment-and-production/6.choosing-a-host",{"title":161,"icon":47,"defaultOpen":47,"path":162,"stem":163,"children":164,"page":47},"Customization","/docs/customizing-the-image","docs/5.customizing-the-image",[165,169,173,177,181],{"title":166,"path":167,"stem":168},"Changing php.ini settings","/docs/customizing-the-image/changing-common-php-settings","docs/5.customizing-the-image/1.changing-common-php-settings",{"title":170,"path":171,"stem":172},"Installing PHP extensions","/docs/customizing-the-image/installing-additional-php-extensions","docs/5.customizing-the-image/2.installing-additional-php-extensions",{"title":174,"path":175,"stem":176},"Adding start up scripts","/docs/customizing-the-image/adding-your-own-start-up-scripts","docs/5.customizing-the-image/3.adding-your-own-start-up-scripts",{"title":178,"path":179,"stem":180},"Using S6 Overlay","/docs/customizing-the-image/using-s6-overlay","docs/5.customizing-the-image/4.using-s6-overlay",{"title":182,"path":183,"stem":184},"Understanding file permissions","/docs/customizing-the-image/understanding-file-permissions","docs/5.customizing-the-image/5.understanding-file-permissions",{"title":186,"icon":47,"defaultOpen":47,"path":187,"stem":188,"children":189,"page":47},"Upgrading","/docs/upgrading","docs/6.upgrading",[190,194,198,202],{"title":191,"path":192,"stem":193},"Upgrade guide","/docs/upgrading/upgrade-guide","docs/6.upgrading/1.upgrade-guide",{"title":195,"path":196,"stem":197},"Upgrade to v5","/docs/upgrading/upgrade-to-v5","docs/6.upgrading/2.upgrade-to-v5",{"title":199,"path":200,"stem":201},"Upgrade to v4","/docs/upgrading/upgrade-to-v4","docs/6.upgrading/3.upgrade-to-v4",{"title":203,"path":204,"stem":205},"Upgrade to v3","/docs/upgrading/upgrade-to-v3","docs/6.upgrading/4.upgrade-to-v3",{"title":207,"path":208,"stem":209,"children":210,"page":47},"Troubleshooting","/docs/troubleshooting","docs/7.troubleshooting",[211,215],{"title":212,"path":213,"stem":214},"Common issues","/docs/troubleshooting/common-issues","docs/7.troubleshooting/1.common-issues",{"title":216,"path":217,"stem":218},"Getting help","/docs/troubleshooting/getting-help","docs/7.troubleshooting/2.getting-help",{"title":220,"path":221,"stem":222,"children":223,"page":47},"Security","/docs/security","docs/8.security",[224,228,232],{"title":225,"path":226,"stem":227},"How images are built","/docs/security/how-images-are-built","docs/8.security/1.how-images-are-built",{"title":229,"path":230,"stem":231},"Verifying images","/docs/security/verifying-images","docs/8.security/2.verifying-images",{"title":233,"path":234,"stem":235},"Vulnerability scanning","/docs/security/vulnerability-scanning","docs/8.security/3.vulnerability-scanning",{"title":237,"path":238,"stem":239,"children":240,"page":47},"Reference","/docs/reference","docs/9.reference",[241,245],{"title":242,"path":243,"stem":244},"Environment variable specification","/docs/reference/environment-variable-specification","docs/9.reference/1.environment-variable-specification",{"title":246,"path":247,"stem":248},"Command reference","/docs/reference/command-reference","docs/9.reference/2.command-reference",{"id":250,"title":182,"body":251,"description":737,"extension":738,"links":739,"meta":740,"navigation":429,"path":183,"redirect":739,"seo":743,"stem":184,"__hash__":744},"docs/docs/5.customizing-the-image/5.understanding-file-permissions.md",{"type":252,"value":253,"toc":732},"minimark",[254,269,274,291,294,327,331,352,356,362,390,397,524,531,641,652,698,717,728],[255,256,257],"lead-p",{},[258,259,260,261,265,266,268],"p",{},"The images run as the unprivileged ",[262,263,264],"code",{},"www-data"," user. When you mount your code from the host, files the container writes belong to ",[262,267,264],{},"'s user ID. Files it needs to change must be writable by that ID. This page shows how to make the container's user match yours in development.",[270,271,273],"h2",{"id":272},"why-permissions-break-with-mounted-code","Why permissions break with mounted code",[258,275,276,278,279,282,283,286,287,290],{},[262,277,264],{}," is UID and GID ",[262,280,281],{},"33"," on Debian and ",[262,284,285],{},"82"," on Alpine. Your host user is usually something else, such as ",[262,288,289],{},"1000",", and every developer on a team may have a different ID.",[258,292,293],{},"With your code mounted as a volume:",[295,296,297,309],"ul",{},[298,299,300,301,304,305,308],"li",{},"Files the container creates, such as logs and cache files, belong to ",[262,302,303],{},"33:33"," on your host, so you need ",[262,306,307],{},"sudo"," to edit or delete them.",[298,310,311,312,314,315,318,319,322,323,326],{},"Directories owned by your host user may not be writable by ",[262,313,281],{},", so PHP fails with ",[262,316,317],{},"Permission denied"," when it writes to ",[262,320,321],{},"storage/"," or ",[262,324,325],{},"bootstrap/cache/",".",[270,328,330],{"id":329},"why-the-images-dont-change-the-user-at-startup","Why the images don't change the user at startup",[258,332,333,334,337,338,341,342,345,346,348,349,351],{},"Some images accept ",[262,335,336],{},"PUID"," and ",[262,339,340],{},"PGID"," variables and change the user when the container starts. That needs the container to start as ",[262,343,344],{},"root",". Files created before the switch, such as early log files, can end up owned by ",[262,347,344],{}," and no longer writable by ",[262,350,264],{},". These images stay unprivileged instead. You change the user ID when you build the image.",[270,353,355],{"id":354},"match-your-user-id-in-development","Match your user ID in development",[258,357,358,359,361],{},"Two helper scripts do the work at build time. Both must run as ",[262,360,344],{},":",[295,363,364,373],{},[298,365,366,369,370,372],{},[262,367,368],{},"docker-php-serversideup-set-id www-data \u003Cuid>:\u003Cgid>"," changes ",[262,371,264],{},"'s UID and GID.",[298,374,375,378,379,382,383,386,387,326],{},[262,376,377],{},"docker-php-serversideup-set-file-permissions --owner \u003Cuid>:\u003Cgid>"," gives the image's own files back to that user: ",[262,380,381],{},"/var/www",", ",[262,384,385],{},"/composer",", and the web server's configuration, log, and certificate directories. It detects the variation, or you can pass ",[262,388,389],{},"--service",[258,391,392,393,396],{},"Use a multi-stage ",[262,394,395],{},"Dockerfile"," so only the development target changes the user. Production keeps the default:",[398,399,403],"pre",{"className":400,"code":401,"filename":395,"language":402,"meta":10,"style":10},"language-dockerfile shiki shiki-themes github-dark","FROM serversideup/php:8.5-fpm-nginx AS base\n\nFROM base AS development\nARG USER_ID\nARG GROUP_ID\n\nUSER root\nRUN docker-php-serversideup-set-id www-data $USER_ID:$GROUP_ID && \\\n    docker-php-serversideup-set-file-permissions --owner $USER_ID:$GROUP_ID\nUSER www-data\n\nFROM base AS production\nCOPY --chown=www-data:www-data . /var/www/html\n","dockerfile",[262,404,405,424,431,444,453,461,466,475,484,490,498,503,515],{"__ignoreMap":10},[406,407,410,414,418,421],"span",{"class":408,"line":409},"line",1,[406,411,413],{"class":412},"snl16","FROM",[406,415,417],{"class":416},"s95oV"," serversideup/php:8.5-fpm-nginx ",[406,419,420],{"class":412},"AS",[406,422,423],{"class":416}," base\n",[406,425,427],{"class":408,"line":426},2,[406,428,430],{"emptyLinePlaceholder":429},true,"\n",[406,432,434,436,439,441],{"class":408,"line":433},3,[406,435,413],{"class":412},[406,437,438],{"class":416}," base ",[406,440,420],{"class":412},[406,442,443],{"class":416}," development\n",[406,445,447,450],{"class":408,"line":446},4,[406,448,449],{"class":412},"ARG",[406,451,452],{"class":416}," USER_ID\n",[406,454,456,458],{"class":408,"line":455},5,[406,457,449],{"class":412},[406,459,460],{"class":416}," GROUP_ID\n",[406,462,464],{"class":408,"line":463},6,[406,465,430],{"emptyLinePlaceholder":429},[406,467,469,472],{"class":408,"line":468},7,[406,470,471],{"class":412},"USER",[406,473,474],{"class":416}," root\n",[406,476,478,481],{"class":408,"line":477},8,[406,479,480],{"class":412},"RUN",[406,482,483],{"class":416}," docker-php-serversideup-set-id www-data $USER_ID:$GROUP_ID && \\\n",[406,485,487],{"class":408,"line":486},9,[406,488,489],{"class":416},"    docker-php-serversideup-set-file-permissions --owner $USER_ID:$GROUP_ID\n",[406,491,493,495],{"class":408,"line":492},10,[406,494,471],{"class":412},[406,496,497],{"class":416}," www-data\n",[406,499,501],{"class":408,"line":500},11,[406,502,430],{"emptyLinePlaceholder":429},[406,504,506,508,510,512],{"class":408,"line":505},12,[406,507,413],{"class":412},[406,509,438],{"class":416},[406,511,420],{"class":412},[406,513,514],{"class":416}," production\n",[406,516,518,521],{"class":408,"line":517},13,[406,519,520],{"class":412},"COPY",[406,522,523],{"class":416}," --chown=www-data:www-data . /var/www/html\n",[258,525,526,527,530],{},"Build the ",[262,528,529],{},"development"," target with your IDs in Compose:",[398,532,537],{"className":533,"code":534,"filename":535,"language":536,"meta":10,"style":10},"language-yaml shiki shiki-themes github-dark","services:\n  php:\n    build:\n      context: .\n      target: development\n      args:\n        USER_ID: ${UID}\n        GROUP_ID: ${GID}\n    ports:\n      - 80:8080\n    volumes:\n      - .:/var/www/html\n","compose.yml","yaml",[262,538,539,548,555,562,574,585,592,602,612,619,627,634],{"__ignoreMap":10},[406,540,541,545],{"class":408,"line":409},[406,542,544],{"class":543},"s4JwU","services",[406,546,547],{"class":416},":\n",[406,549,550,553],{"class":408,"line":426},[406,551,552],{"class":543},"  php",[406,554,547],{"class":416},[406,556,557,560],{"class":408,"line":433},[406,558,559],{"class":543},"    build",[406,561,547],{"class":416},[406,563,564,567,570],{"class":408,"line":446},[406,565,566],{"class":543},"      context",[406,568,569],{"class":416},": ",[406,571,573],{"class":572},"sDLfK",".\n",[406,575,576,579,581],{"class":408,"line":455},[406,577,578],{"class":543},"      target",[406,580,569],{"class":416},[406,582,584],{"class":583},"sU2Wk","development\n",[406,586,587,590],{"class":408,"line":463},[406,588,589],{"class":543},"      args",[406,591,547],{"class":416},[406,593,594,597,599],{"class":408,"line":468},[406,595,596],{"class":543},"        USER_ID",[406,598,569],{"class":416},[406,600,601],{"class":583},"${UID}\n",[406,603,604,607,609],{"class":408,"line":477},[406,605,606],{"class":543},"        GROUP_ID",[406,608,569],{"class":416},[406,610,611],{"class":583},"${GID}\n",[406,613,614,617],{"class":408,"line":486},[406,615,616],{"class":543},"    ports",[406,618,547],{"class":416},[406,620,621,624],{"class":408,"line":492},[406,622,623],{"class":416},"      - ",[406,625,626],{"class":583},"80:8080\n",[406,628,629,632],{"class":408,"line":500},[406,630,631],{"class":543},"    volumes",[406,633,547],{"class":416},[406,635,636,638],{"class":408,"line":505},[406,637,623],{"class":416},[406,639,640],{"class":583},".:/var/www/html\n",[258,642,643,644,647,648,651],{},"Compose reads these from your environment. Bash doesn't export ",[262,645,646],{},"UID"," and doesn't set ",[262,649,650],{},"GID"," at all. Export both before you run Compose. To make it permanent, add the line to your shell profile:",[398,653,658],{"className":654,"code":655,"filename":656,"language":657,"meta":10,"style":10},"language-bash shiki shiki-themes github-dark","export UID GID=$(id -g)\ndocker compose up --build\n","Terminal","bash",[262,659,660,684],{"__ignoreMap":10},[406,661,662,665,668,671,674,678,681],{"class":408,"line":409},[406,663,664],{"class":412},"export",[406,666,667],{"class":416}," UID GID",[406,669,670],{"class":412},"=",[406,672,673],{"class":416},"$(",[406,675,677],{"class":676},"svObZ","id",[406,679,680],{"class":572}," -g",[406,682,683],{"class":416},")\n",[406,685,686,689,692,695],{"class":408,"line":426},[406,687,688],{"class":676},"docker",[406,690,691],{"class":583}," compose",[406,693,694],{"class":583}," up",[406,696,697],{"class":572}," --build\n",[258,699,700,702,703,705,706,709,710,712,713,716],{},[262,701,264],{}," in the container now has your UID and GID. You can edit and delete the files it creates without ",[262,704,307],{},". Build the ",[262,707,708],{},"production"," target for deployment; it uses the default ",[262,711,303],{}," (or ",[262,714,715],{},"82:82"," on Alpine).",[258,718,719,727],{},[720,721,726],"a",{"href":722,"rel":723,"target":725},"https://serversideup.net/open-source/spin/",[724],"nofollow","_blank","Spin"," sets the user and group IDs for you if you'd rather not manage this yourself.",[729,730,731],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}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 .s4JwU, html code.shiki .s4JwU{--shiki-default:#85E89D}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}",{"title":10,"searchDepth":426,"depth":426,"links":733},[734,735,736],{"id":272,"depth":426,"text":273},{"id":329,"depth":426,"text":330},{"id":354,"depth":426,"text":355},"Match the container user to your host user in development while keeping production images unprivileged.","md",null,{"head":741,"layout":7},{"title":742},"Understanding file permissions - Docker PHP - Server Side Up",{"title":182,"description":737},"V7_VmyEu3d92kxdXy5xxf6w_xm-l213lrbS8UHstI2g",[746,748],{"title":178,"path":179,"stem":180,"description":747,"children":-1},"How the fpm-nginx and fpm-apache images use S6 Overlay, and how to add your own long-running service.",{"title":191,"path":192,"stem":193,"description":749,"children":-1},"How serversideup/php releases and tags work, which tag to use, and how to patch an image yourself.",1793811945434]