Opened 20 months ago
Last modified 43 hours ago
#57896 new enhancement
Improve devcontainer + Codespaces support
Reported by: | SergeyBiryukov | Owned by: | |
---|---|---|---|
Milestone: | Future Release | Priority: | normal |
Severity: | normal | Version: | |
Component: | Build/Test Tools | Keywords: | has-patch |
Focuses: | Cc: |
Description
Background: #57187.
Codespaces support was introduced in [55303] and adjusted in [55353].
@johnbillion raised some follow-up points in comment:23:ticket:57187:
README.md
needs to document the three environment choices now available to devs (Codespaces, local devcontainer, local environment).- The devcontainer doesn't use the same environment for WordPress that you get when you follow the "Local development" instructions in the readme. We're going to end up with two confusingly separate but similar environments. Could and should the same environment be used to run WordPress within the devcontainer?
setup.sh
assumes the workspace directory name is/workspaces/wordpress-develop
but the local directory name may differ. The${localWorkspaceFolderBasename}
variable needs to be passed in to that script fromdevcontainer.json
.
Change History (22)
This ticket was mentioned in PR #5115 on WordPress/wordpress-develop by rmccue.
15 months ago
#2
- Keywords has-patch added
- Switches from docker-in-docker to docker-outside-of-docker to fix
docker
CLI commands - Mounts
/src
into the container so that Codespaces *actually* runs trunk - Fixes the host mapping problem by using overridden host name
- Removes unneeded, potentially-inaccurate cd call
Trac ticket: https://core.trac.wordpress.org/ticket/57896
#4
follow-up:
↓ 6
@
15 months ago
I think the behaviour you were seeing with docker-compose cli ... working was because it was starting a new CLI service.
Agreed. I don't remember the details or what all I tried, but I think the issue was that the initial containers were created in one configuration with respect to the devcontainer container (as children? as siblings?) and the newly created CLI container was created with another.
I also tried switching over to use the main docker-compose we already have, but that causes errors for some reason - it's very hard to see in the build logs exactly why that happens.
As best I can tell, docker-outside-of-docker
isn't working with core's docker-compose.yml because of nginx:alpine
, which doesn't have apt-get
(see docker-outside-of-docker's install.sh, OS Support). Alpine uses apk. Switching to nginx:latest
fixes that problem, though others crop up.
I'll drop a link on your PR to some changes that mostly work.
15 months ago
#5
Nice! The docker-outside-of-docker
definitely looks better. I tried getting codespaces to use the base docker-compose.yml, and was partly successful:
- Switches from
nginx:alpine
(noapt-get
- it uses `apk`) tonginx:latest
. See OS Support, source. - Skips manual wp-cli install (the base docker-compose.yml includes a wp-cli image).
- Skips chromium install for now.
- Hacks around some weirdness I don't understand with the wp-cli container's volumes.
- Skips the wp-config.php generation and WP installation steps since
npm run env:install
doesn't behave correctly. Those need to be done manually with these changes for now:docker-compose run --rm cli config create --dbname=wordpress_develop --dbuser=root --dbpass=password --dbhost=mysql --path=/var/www/src --force docker-compose run --rm cli core install --title="WordPress Develop" --admin_user=admin --admin_password=password --admin_email=test@test.com --skip-email --url=http://localhost:8889
(Note thatnpm run env:install
does more than just those two things. We should get that script working in this environment and use it.)
#6
in reply to:
↑ 4
;
follow-up:
↓ 9
@
15 months ago
Replying to mdawaffe:
Agreed. I don't remember the details or what all I tried, but I think the issue was that the initial containers were created in one configuration with respect to the devcontainer container (as children? as siblings?) and the newly created CLI container was created with another.
Yeah, the detail I'd missed is that when in dockerComposeFile mode, service
indicates which container to run the terminal in - that's new behaviour since last time I tried Codespaces!
tl;dr of the behaviour: Codespaces is running docker-compose
on the root VM, then your terminal/etc run inside the specified service via an extended compose file. To access the cntainers, you hence have to mount the Docker socket into that service; docker-outside-of-docker handles that, thankfully, although I only realised that after I'd finished implementing the old school hacks.
As best I can tell,
docker-outside-of-docker
isn't working with core's docker-compose.yml because ofnginx:alpine
, which doesn't haveapt-get
(see docker-outside-of-docker's install.sh, OS Support). Alpine uses apk. Switching tonginx:latest
fixes that problem, though others crop up.
I actually did manage to get it to work in the end... -ish. Rather than using core's containers for the "main" (service
) container, I'm using a container built off mcr.microsoft.com/devcontainers/base
with an extended docker-compose, which means we don't need to modify the main file (but can override it if needed).
My experience with Codespaces and in-container development is that it's very useful to have a devtool-only container available for working tools. (You can also use the cli
container by setting the command to sleep infinity
, but it's a bit more janky, and doesn't give us an easy way to add additional tools.)
The problem I ended up with though is that MySQL is not accepting connections for root from 172.18.0.0/16; the config should be allowing %
for the host so not sure what's going on there.
I'll PR this up too in a bit (my Codespace is crashy right now).
I'd recommend we commit either PR 5115 or something like it in the short term to fix the current experience while we look at using the other containers though.
This ticket was mentioned in PR #5119 on WordPress/wordpress-develop by rmccue.
15 months ago
#7
Building off #5115, this switches Codespaces to use the docker-compose.yml we include for core development.
This is currently broken as MySQL is refusing connections, even with the change to the bind-address
in the command. Still working on how to fix that one.
cc @mdawaffe - note I've added an extra "devcontainer" container here, so it doesn't require changing from alpine for the nginx container. That said, still broken.
Trac ticket: https://core.trac.wordpress.org/ticket/57896
15 months ago
#8
Curiously, mysqladmin
inside the container also does not connect:
$ docker compose exec -it mysql bash bash-4.2# mysqladmin status mysqladmin: connect to server at 'localhost' failed error: 'Access denied for user 'root'@'localhost' (using password: NO)'
(Even when forcing --protocol=socket
)
#9
in reply to:
↑ 6
;
follow-up:
↓ 12
@
15 months ago
Replying to rmccue:
I actually did manage to get it to work in the end... -ish. Rather than using core's containers for the "main" (
service
) container, I'm using a container built offmcr.microsoft.com/devcontainers/base
with an extended docker-compose, which means we don't need to modify the main file (but can override it if needed).
That's what I was going to try next. Thank you for beating me to it :)
The problem I ended up with though is that MySQL is not accepting connections for root from 172.18.0.0/16; the config should be allowing
%
for the host so not sure what's going on there.
Pretty sure this is not a bind issue. I ran into this as well: The MySQL container is not running its initialization:
- https://github.com/docker-library/mysql/blob/c13cda9c2c9d836af9b3331e8681f8cc8e0a7803/5.7/docker-entrypoint.sh#L302-L305
- https://github.com/docker-library/mysql/blob/c13cda9c2c9d836af9b3331e8681f8cc8e0a7803/5.7/docker-entrypoint.sh#L416
(You can tell since the user.myd file is 0 bytes.)
It magically fixed itself when I committed my changes to my own fork rather than having uncommitted changes in yours. (Correlated not causal, I suspect.)
15 months ago
#10
Looks like my attempts to fix the problem was hidden by cached data on the volume per @mdawaffe on https://core.trac.wordpress.org/ticket/57896#comment:9
Changing the volume's name to force invalidation fixes this, or you can do some voodoo to delete the volume.
Anyway, that's fixed, and now there's a problem with the installer, which is that it waits forever on the container to be up - localhost:8889 isn't accessible from the container for some reason, but works fine via the browser, so there's some sort of networking issue there.
In the process, I updated the installer to insert the host hack from #5115 if it detects it's running in Codespaces, as well as permitting LOCAL_URL
to be passed instead of just LOCAL_PORT
.
15 months ago
#11
Fixed the networking issue by moving the devcontainer from the bridge network to the host network. You won't be able to do mysql -h mysql
, but you can do curl localhost:8889
as you'd expect, so I think that's fine.
I also had to remove chromium
as it's not available on the devcontainer distro's package manager (Ubuntu), and per https://core.trac.wordpress.org/ticket/57896#comment:1 it's very slow anyway.
#12
in reply to:
↑ 9
;
follow-up:
↓ 14
@
15 months ago
Replying to mdawaffe:
Pretty sure this is not a bind issue. I ran into this as well: The MySQL container is not running its initialization:
I think in the end it was both a bind issue and data sticking around inside the volume, which I managed to flush out.
https://github.com/WordPress/wordpress-develop/pull/5119 should now be working as expected - I'd still say we stick with https://github.com/WordPress/wordpress-develop/pull/5115 as an immediate fix until 5119 has some more testing on it, but I'm not super fussed.
15 months ago
#13
The CLI container is broken for me in this PR: ls /var/www
shows an empty directory.
This is because the CLI container is not created during the Codespace creation (well - one such container is created, but it immediately exits/stops). Instead, CLI containers are spun up as necessary for each CLI command. Since these containers are being created within the devcontainer container, and since we're "proxying" docker and docker.sock from the "real" host, we need to specify volume sources with the *host's* absolute directories, not the devcontainer container's directories (relative or absolute).
This fixes it for me: https://gist.github.com/mdawaffe/f46496261af01a408f93e2caabae512c
There may be a cleaner way to do that without changing the root docker-compose.yml, but then all CLI commands would have to be run as:
docker-compose -f docker-compose.yml -f .devcontainer/docker-compose.codespaces.yml run --rm cli …
Which would require a bunch of changes to tools/local-env/scripts/docker.js
and tools/local-env/scripts/install.js
.
This is also the reason that any npm run env:cli
call yields:
WARN[0000] Found orphan containers ([wordpress-develop_devcontainer_1]) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up.
The root docker-compose.yml doesn't know anything about the devcontainer service, so it thinks that container is orphaned. Perhaps those changes to the various local-env scripts are warranted. (Though env:stop
shouldn't turn off the devcontainer container :)).
#14
in reply to:
↑ 12
@
15 months ago
Replying to rmccue:
I'd still say we stick with https://github.com/WordPress/wordpress-develop/pull/5115 as an immediate fix until 5119 has some more testing on it, but I'm not super fussed.
I like 5119 (though there's still a little wonkiness) more than 5115 because the non-core WordPress docker image makes me sad :) but I am likewise unfussed.
This ticket was mentioned in Slack in #core by jeffpaul. View the logs.
15 months ago
15 months ago
#16
There may be a cleaner way to do that without changing the root docker-compose.yml
Subjectively "cleaner" method here: https://gist.github.com/mdawaffe/1bf45cafaa6bd7115cbde93101fb8207
All(? I didn't try everything) npm run
commands work (including stop, start, etc.) except npm run env:install
(the most useful one :)) since LOCAL_URL
is not set. npm run env:install
still works within setup.sh, since that file sets the variable. I guess we could copy that code from setup.sh to install.js?
I'm not sure how important it is that npm run env:stop
etc. work, but it feels nice: the codespace environment behaves more like the local dev environment.
15 months ago
#17
The CLI container is broken for me in this PR:
ls /var/www
shows an empty directory.
That is... strange. I'm not seeing that:
@rmccue ➜ /workspaces/wordpress-develop (unify-docker-compose-codespaces) $ docker-compose run --entrypoint /bin/bash cli WARN[0000] Found orphan containers ([wordpress-develop_devcontainer_1]) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up. root@13a841c7de49:/var/www# ls -al total 1324 drwxrwxrwx+ 10 wp_php root 4096 Aug 30 16:47 . drwxr-xr-x 1 root root 4096 Nov 15 2022 .. drwxrwxrwx+ 2 wp_php root 4096 Aug 24 18:30 .cache drwxrwxrwx+ 3 wp_php root 4096 Aug 30 16:50 .devcontainer -rw-rw-rw- 1 wp_php root 454 Aug 24 18:30 .editorconfig -rw-rw-rw- 1 wp_php root 1844 Aug 30 01:17 .env -rw-rw-rw- 1 wp_php root 268 Aug 24 18:30 .eslintignore
I *am* seeing the orphan containers warning you note though due to the multiple file issue; worth noting that the full command Codespaces runs also includes a bunch of other files too to set various other mount points, so not sure if we need to account for that.
The issue in theory makes sense though given the switch from docker-in-docker to docker-outside-of-docker.
Subjectively "cleaner" method here: https://gist.github.com/mdawaffe/1bf45cafaa6bd7115cbde93101fb8207
It might make sense to have a $LOCAL_ROOT_DIR
used in the main docker-compose to avoid needing to override this in our Codespaces file? I can see these getting out of sync pretty quickly, and seems like it might be useful in the generic case anyway.
All(? I didn't try everything)
npm run
commands work (including stop, start, etc.) exceptnpm run env:install
(the most useful one :)) sinceLOCAL_URL
is not set.npm run env:install
still works within setup.sh, since that file sets the variable. I guess we could copy that code from setup.sh to install.js?
There's probably no real reason not to just set LOCAL_URL
in our devcontainer.json
if we can - I think all the vars are already in scope anyway.
14 months ago
#18
I wonder if we're making things too complicated for ourselves.
How about we combine the existing setup (Docker-in-Docker) with your setup (separate devcontainer container)? We'd get the benefits of both: no host v. container path weirdness with Docker-outside-of-Docker so no need to make any changes to docker-compose.yml, and a simpler devcontainer configuration.
I tested that here:
https://github.com/WordPress/wordpress-develop/compare/trunk...mdawaffe:wordpress-develop:codespaces-did-experiment
The diff is pretty simple, and so far everything works the same as in local development: npm run env:start
, docker ps
, npm run env:install
, npm run env:cli
, npm run env:restart
, npm run test:php
, etc.
#19
@
12 months ago
Just chiming in here that, taking the current Dev Container setup as a loose example, I was able to setup a fully working Codespaces, and local Dev Container, setup where a specific version of WordPress is installed. My setup is for plugin development, and uses a Composer-based install of WordPress, however, the working solution should work properly with the wordpress-develop
repo using it as the WordPress install. There were some required adjustments needed to both the docker-compose.yml
file as well as the wp-config.php
file being used to drive the site especially when running behind the Codespaces proxy.
My working bits are here:
- https://github.com/forumone/wp-cfm/tree/develop/.devcontainer
- https://github.com/forumone/wp-cfm/blob/develop/docker-compose.yml
- https://github.com/forumone/wp-cfm/blob/develop/tools/local-env/wp-config.php#L96-L116
I didn't take the time to read through all of the comments here in detail to account for any desired changes to the setup. I can give a crack at this and open up a PR with something that will hopefully work.
One additional nice benefit is that the local Dev Container can be used with Visual Studio Code but also other IDE by using the DevPod tool which has full support for Dev Containers. I have been able to successfully use PhpStorm for example with starting up the Dev Container via DevPod and then just using an SSH terminal to have the container in the PhpStorm terminal. JetBrains support for Dev Containers is in beta and is pretty lacking but this may be more integrated in the future.
12 months ago
#20
Just noting that this setup is not a universally compatible Dev Container setup. This assumes that running the Dev Container is only every being done in Codespaces. This is an incorrect use of Dev Containers. Dev Containers can also be used locally only and this setup should allow for this. I have personally been completely dropping the use of wp-env
because of it's lack of flexibility and it's inherit requirement that I have a NodeJS version installed on my local machine. The whole point of a Dev Container is to have the entire development environment self contained, which includes NodeJS. You can see what the changes I made here. https://github.com/forumone/wp-cfm/tree/develop/.devcontainer
Is wp-env
really a sustainable development environment tool going forward? It is heavy always spinning up Dev & Testing environments. It's inflexible for any sort of plugin that integrates with anything outside of WordPress where you want to include other Docker services for the purposes of integration tests. A Dev Container setup easily provides both an online and local consistent development environment that is open to expansion and changes needed by any plugins.
#21
@
11 months ago
So I have finally this week completed the creation of a multi-platform Docker image that is a prebuilt image from the Dev Container that I setup. This image includes all of the necessary tools for local plugin and theme development and allows for the Dev Container to be quickly spun up. I will get a pull request opened that will incorporate my custom images and the fixes so that the wordpress-develop Dev Container will work again.
https://github.com/oidc-wp/openid-connect-generic/tree/develop/.devcontainer
#22
@
43 hours ago
FWIW, I'm also seeing the issue with orphaned containers in trunk
:
WARN[0000] Found orphan containers ([wordpress-develop-php-run-db9aae0948cf wordpress-develop-php-run-06b0d0ddd201]) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up.
This is right after having done npm run env:clean
. The env cleaning became critical for me because it seems like very time a unit test fails, a container gets orphaned. So my terminal was looking like this whenever I run something like npm run test:php -- --filter=test_ensure_next_token_method_extensibility
:
Found orphan containers ([wordpress-develop-php-run-1d18dab826b9 wordpress-develop-php-run-c0a351bb7016 wordpress-develop-php-run-2ef48baec74f wordpress-develop-php-run-3114f4e20fc7 wordpress-develop-php-run-62eb4f6a4f52 wordpress-develop-php-run-c4c37e56b396 wordpress-develop-php-run-85e1b8aa4b4b wordpress-develop-php-run-2c075811b2f1 wordpress-develop-php-run-b23f40fc765a wordpress-develop-php-run-711fc2e10627 wordpress-develop-php-run-feaa9669d1fb wordpress-develop-php-run-c09538e98af1 wordpress-develop-php-run-cd8dca61fdd1 wordpress-develop-php-run-f78d211be037 wordpress-develop-php-run-181546b4bda4 wordpress-develop-php-run-5c10882f19ca wordpress-develop-php-run-532f6afa2d2f wordpress-develop-php-run-5303587781f1 wordpress-develop-php-run-0f632b9ca632 wordpress-develop-php-run-8966bc973968 wordpress-develop-php-run-e0c50bc44e63 wordpress-develop-php-run-27fbb7f930f1 wordpress-develop-php-run-47da93b3d692 wordpress-develop-php-run-15016a6816a1 wordpress-develop-php-run-5a19ba31938b wordpress-develop-php-run-b71bda7b4efc wordpress-develop-php-run-1dcc8521a7a1 wordpress-develop-php-run-d6ba1fc4b149 wordpress-develop-php-run-695effd5f56b wordpress-develop-php-run-af081641e5b6 wordpress-develop-php-run-b9495834f590 wordpress-develop-php-run-414b5888efe6 wordpress-develop-php-run-de1e8c0e4ae0 wordpress-develop-php-run-10f308133154 wordpress-develop-php-run-21c87d13521d wordpress-develop-php-run-646feb579687 wordpress-develop-php-run-67ae4f931837 wordpress-develop-php-run-c503486e1768 wordpress-develop-php-run-ce4b5c081c9e wordpress-develop-php-run-2e3b537ee95f wordpress-develop-php-run-e83acbae1c61 wordpress-develop-php-run-19a86ef3ca91 wordpress-develop-php-run-cd8a2eb29acb wordpress-develop-php-run-8863a66ed356 wordpress-develop-php-run-119031f1dd4c wordpress-develop-php-run-9f53dd1052ba wordpress-develop-php-run-33609e55aa94 wordpress-develop-php-run-0f22120e65c0 wordpress-develop-php-run-48ec1c40e563 wordpress-develop-php-run-c91850453bf1 wordpress-develop-php-run-ed52fb374b3c wordpress-develop-php-run-2f8859a03e9b wordpress-develop-php-run-632b5bb530a8 wordpress-develop-php-run-f0b1c7cb44e7 wordpress-develop-php-run-fa6f8f26eddd wordpress-develop-php-run-ab68305a9f20 wordpress-develop-php-run-a40e4fa1b9a0 wordpress-develop-php-run-b9a6eb2b1b69 wordpress-develop-php-run-cce5a1e023aa wordpress-develop-php-run-64ec69f26438 wordpress-develop-php-run-6f005ac54f63 wordpress-develop-php-run-eacf903b7ae4 wordpress-develop-php-run-bc7e9e76cd5e wordpress-develop-php-run-10f7e1a63b33 wordpress-develop-php-run-854586c027ef]) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up.
@helen, @mdawaffe, @jeremyfelt and I all worked on Codespaces support a bit during WCUS contributor day, and there were a few key issues we noted in addition to the aforementioned ones:
https://...-443.app.github.dev/
docker ps
ordocker logs
doesn't show the running containersWe didn't fully debug it during contributor day due to the terrible wifi, but I picked it back up today and sorted a few of these. Namely:
../src:/var/www/html
will override the WP version with the version insrc/
, fixing this issue$_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST']
will fix this issue (copied from the Codespaces setup on Altis)"service"
, i.e.app
. (This is new config I'd not seen before.) Switching to use docker-outside-of-docker instead handles mounting the Docker binds correctly, and allows you to view running containers and logs properly.I'll PR this patch soon.
@mdawaffe I think the behaviour you were seeing with
docker-compose cli ...
working was because it was starting a new CLI service.I also tried switching over to use the main docker-compose we already have, but that causes errors for some reason - it's very hard to see in the build logs exactly why that happens.
Additionally, the
cd
in thesetup.sh
appears to be useless -pwd
is already/workspaces/wordpress-develop
anyway.A few other things I think we should aim to improve:
wordpress
container rather than our own, it's also not a devcontainer-specific container - some tools like npm are hence out-of-date. It may be worth making our own for this specific reason, even if we can't switch to using the basedocker-compose.yml
config.