Are you sure that it can find the txt file (did you try a full path for that too) ? PHP's current path can be different than the one on your console. Show
All 6 Repliesrch1231 169 Posting Shark 2 things: 0 0 Share jrhitokiri 0 Newbie Poster 2 things: full path didn't help pasting it into command line, it functions normally and outputs the 2 lines (as mentioned in my orig post) Any other suggestions? 0 0 Share pritaeas 2,130 ¯\_(ツ)_/¯ Moderator Featured Poster Are you sure that it can find the txt file (did you try a full path for that too) ? PHP's current path can be different than the one on your console. 0 0 Share jrhitokiri 0 Newbie Poster Are you sure that it can find the txt file (did you try a full path for that too) ? PHP's current path can be different than the one on your console. Yep, fill path for both the grep command and the text file. 0 0 Share smantscheff 265 Veteran Poster 11 Years AgoAlso have a look at the preg functions of PHP which might be much easier to handle than the external grep. 0 0 Share jrhitokiri 0 Newbie Poster 11 Years Ago
The thing is, I'm searching a 1GB file and I fear that the preg is significantly slower than the grep external function. :< You probably heard from the new kid around the block called "Docker"? You are a PHP developer and would like to get into that, but you didn't have the time to look into it, yet? Then this tutorial is for you! By the end of it, you should know: - how to set up Docker "natively" on a Windows 10 machine - how to build and run containers from the command line - how to log into containers and explore them for information - what a Dockerfile is and how to use it - how containers can talk to each other - how 20 can be used to fit everything nicely togetherNote: I will not only walk on the happy path during this tutorial. That means I'll deep-dive into some things that are not completely related to docker (e.g. how to find out where the configuration files for php-fpm are located), but that are imho important to understand, because they enable you to solve problems later on your own. But if you are short on time, you might also jump directly to . All code samples are publicly available in my Docker PHP Tutorial repository on Github. The branch for this tutorial is part_1_setting-up-php-php-fpm-and-nginx-for-local-development-on-docker. All published parts of the Docker PHP Tutorial are collected under a dedicated page at Docker PHP Tutorial. The following part is Setting up PhpStorm with Xdebug for local development on Docker . If you want to follow along, please subscribe to the RSS feed or to get automatic notifications when the next part comes out :) Table of contents
IntroductionPreconditionsI'm assuming that you have installed Git bash for Windows. If not, please do that before, see . Why use Docker?I won't go into too much detail what Docker is and why you should use it, because others have already talked about this extensively. As for me, my main reasons were - Symlinks in vagrant didn't work the way they should - VMs become bloated and hard to manage over time - Setup in the team involved a lot of work - I wanted to learn Docker for quite some time because you hear a lot about it In general, Docker is kind of like a virtual machine, so it allows us to develop in an OS of our choice (e.g. Windows) but run the code in the same environment as it will in production (e.g. on a linux server). Thanks to its core principles, it makes the separation of services really easy (e.g. having a dedicated server for your database) which - again - is something that should happen on production anyway. Transition from VagrantOn Windows, you can either use the Docker Toolbox (which is essentially a VM with Docker setup on it) or the Hyper-V based Docker for Windows. This tutorial will only look at the latter. A word of caution: Unfortunately, we cannot have other Gods besides Docker (on Windows). The native Docker client requires Hyper-V to be activated which in turn will cause Virtualbox to not work any longer. Thus, we will not be able to use Vagrant and Docker alongside each other. This was actually the main reason it took me so long to start working with Docker. Setup DockerFirst, download Docker for Windows (requires Microsoft Windows 10 Professional or Enterprise 64-bit). The version I am using in this tutorial is 21. During the installation, leave the option "Use Windows Containers instead of Linux containers" unticked as we intend to develop on linux containers (you can change it later anyway).After the installation finishes, we need to log out of Windows and in again. Docker should start automatically. If not, there should be a "Docker for Windows" icon placed on your desktop. If Hyper-V is not activated yet, Docker will automatically urge you to do so now. If you agree, Hyper-V and container features are activated and a reboot is initiated. See Install Hyper-V on Windows 10 to deactivate it again. Caution: VirtualBox will stop working afterwards! Starting one of my previous machines from the VirtualBox interface or via 22 fails with the error message
After rebooting, Docker will start automatically and a welcome screen appears. We can ignore that (close the window). In addition, a new icon is added to your system tray. A right-click reveals the context menu. Open the tab "Shared Devices" and tick the hard drives on your host machine that you want to share with Docker containers. Note: We will still need to define explicit path mappings for the actual containers later on, but the hard drive that the path belongs to must be made available here. After clicking "Apply", you will be prompted for your credentials Next, open tab "Advanced". You don't actually have to change any of the settings but if you (like me) don't have 23 set up as you biggest partition, you might want to change the "Disk image location". I'm putting mine at 24. It might take some minutes for Docker to process the changes.Docker "physically" stores the container images in that location. Congratulations, Docker is now set up on your machine 😊 Setting up the PHP cli containerNow that we have the general stuff out of the way, let's set up our first container. I've created the directory 25 and will run the remaining examples in there.Firstly, lets create a directory for our sourcecode:
For the sake of simplicity, we will stick to the official PHP image and run:
Which means:
The result looks something like this:
Since we don't have the image on our machine (see 26), Docker attempts to pull it from the official registry at https://hub.docker.com/. We've specifically chosen the "7.0-cli" version of the PHP image (which means: PHP 7.0 CLI only). See https://hub.docker.com/_/php/ for a list of all available tags/images.Now let's see if the container is actually running via 27
Weird. For some reason, we don't see our newly created container there. Let's check with the 28 flag to list all containers, even the ones that are not running.
Aha. So the container was created, but immediately stopped (see 29). That's because a container only lives as long as it's main process is running. According to the docs,
This answer explains the difference between CMD and ENTRYPOINT quite well. Since we don't have a Dockerfile defined, we would need to look at the Dockerfile of the base image we're using, but I actually don't wanna go down this rabbit hole for now. Basically, the "problem" is, that the container doesn't have a long running process / service defined, (as the php-fpm or the nginx containers do later on). To keep the container alive, we need to add the 30 flag to the 31 command:
But then this happens:
Apparently, we cannot use the same name ( 32) again. Bummer. So, let's remove the previous container first via
and try again afterwards:
Sweet, so now that the container is up and running, let's "log in" via 0You might get the following error message 1If so, prefixing the command with 33 should help: 2 3A quick 34 within the container verifies, that we can actually run php scripts in there: 4Remember the path mapping, that we specified? Let's create a simple "hello world" script on the windows 10 host machine at 35 to make sure it works: 5Should look like this on the host machine: 6And like this from within the container: 7Let's run the script in the container via 8 9Purrfect. We created the file on our host system and it's automatically available in the container. Installing Xdebug in the PHP containerSince we intend to use Docker for our local development setup, the ability to debug is mandatory. So let's extend our image with the xdebug extension. The readme of the official Docker PHP repository does a good job at explaining . For xdebug, we'll use PECL. To install the extension, make sure to be logged into the container and run 0You should see an output like this: 1The xdebug extension has been build and saved in 36. To actually activate it, run 2That helper command will place the file 37 in the directory for additional php ini files with the content 3which enables the extension. Btw. you can locate the additional php ini files folder by running 4Result: 5When we check the contents of that folder, we will indeed find the 38 file with the before mentioned content and 39 reveals, that xdebug is actually active. 6Now we'll log out of the container (type "exit" or hit 40 + 41) and stop the container via 7 8Now we start the container again via 9log back in and check if xdebug is still there: 0And... it is! So the changes we made "survived" a restart of the container. But: They won't survive a "rebuild" of the container. First we stop and remove the container via 1The 42 flag forces the container to stop. Otherwise we would need an additional 43 before.Then we rebuild it, log in 2and check for xdebug: 3... which won't be there anymore. 4Note the new container ID (before: 44; now: 45) and that 46 doesn't yield anything.Persisting image changes with a DockerfileSimply put, a Dockerfile describes the changes we make to a base image, so we (and everybody else) can easily recreate the same environment. In our case, we need to define the PHP base image that we used as well as instructions for installing and enabling xdebug. To clearly separate infrastructure from code, we'll create a new directory at 47. Create a file named 48 in this directory 5and give it the following content: 6Change to the 47 directory and build the image based on that Dockerfile 7The 50 is actually optional as this is the default anyway. "docker-php-image" is the name of our new image.If you encounter the following error 8you probably missed the trailing 51 at the end of 52 ;) 9Note, that the building takes longer than before, because Docker now needs to do the extra work of installing xdebug. Instead of using the base 53 image, we'll now use our new, shiny 54 image to start the container and check for xdebug. 0 1Aaaand we get an error, because we tried to use the same name ("docker-php"), that we used for the previous, still running container. Sigh.. fortunately we already know how to solve that via 1Retry 0 4Yep, all good. Btw. since we "only" want to check if xdebug was installed, we could also simply pass 55 to the 31 command: 5Be aware that this will create a new container every time it's run (, note the first entry with the wonderful name "distracted_mclean"): 6Before we move on, let's []stop and remove all containers via](https://coderwall.com/p/ewk0mq/stop-remove-all-docker-containers). 7The 57 part returns only the numeric ids of all containers and passes them to the 58 command. 8Setting up a web stack with php-fpm and nginxSince most people are probably not only working on CLI scripts but rather on web pages, the next step in this tutorial is about setting up an nginx web server and connect it to php-fpm. Setting up nginxWe're gonna use the official nginx image and since we don't know anything about that image yet, let's run and explore it a bit: 9yields 0Note that we only used the minimum number of arguments here. Since we did not specify a name, we will simply use the ID instead to log in (so be sure to use the one that your shell returned - don't just copy the line below :P) 1We would expect that there is an nginx process running, but upon checking with 59 we get 2This is common when using docker images, because they are usually kept as minimal as possible. Although this is a good practice in production, it is kind of cumbersome in development. So, let's install 60 via 3and try again: 4Ah. Much better. Lets dig a little deeper and see how the process is configured via 61 5Sweet, so the configuration file is placed in the default location at 62 (see 63). Checking that file will show us, where we need to place additional config files (e.g. for the configuration of our web site). Run 6... and see 7Note the line 64 at the end of the file. In this directory, we'll find the default nginx config: 8 9So the server is listening on port 80. Unfortunately, we cannot reach the web server from our windows host machine, as there is currently (2018-05-31) an open bug for accessing container IPs from a windows host (don't worry, we'll fix that with port mappings in a second)). So, in order to verify that the server is actually working, we'll install 65 inside the nginx container and fetch 66: 0Looks like this: 1Looks good! Now let's customize some stuff: - point the root to 67 - place a "Hello world" index file in 68 2To make the changes become effective, we need to via 3 4Check with curl, et voilá: 5With all that new information we can set up our nginx image with the following folder structure on the host machine: 6 69 7 70 8 71 9Clean up the "exploration" nginx container, 72 into 73 and build the new image: 0 1And then run the "new" container via 2where 3Thanks to the port mapping we can now simply open http://127.0.0.1:8080/ in a browser on the host machine and see the content of our 71 file.If you want some more information about running nginx on Docker, check out this tutorial. Before we move on, let's clean up 4Setting up php-fpmWe are already familiar with the official docker PHP image but have only used the cli-only version so far. FPM ones can be pulled in by using the 75 tags (e.g. like 76). As with nginx, let's explore the php-fpm image first: 5The first thing to note is, that the image automatically exposes port 9000 as a 27 reveals: 6When we examine the Dockerfile that was used to build the image (click here and search for the "7.0-fpm" tag that currently (2018-05-31) links here), we can see that it contains an 78 at the bottom.What else we can we figure out... 7First, will check where the configuration files are located via 79: 8 80 is our suspect. So it is very likely, that we will find the at 81 (unfortunately, we cannot resolve the location directly). 82'ing this file for 83 reveals the location for the : 9 0Hm - a relative path. That looks kinda odd? Let's get a little more context with the 84 option for 82: 1 2Ah - that makes more sense. So we need to resolve 86 relative to 87. Resulting in 88 (usually you'll at least find a 89 file in there). The pool config determines amongst other things how php-fpm listens for connections (e.g. via Unix socket or via TCP IP:port). 3 4php-fpm ist listening on port 9000 on 127.0.0.1 (localhost). So it makes total sense to expose port 9000. Installing xdebugSince we probably also want to debug php-fpm, xdebug needs to be setup as well. The process is pretty much the same as for the cli image: 5Of course we'll also put that in its own Dockerfile: 6 90 7Clean up the test container and build the new image 8Connecting nginx and php-fpmNow that we have containers for nginx and php-fpm, we need to connect them. To do so, we have to make sure that both containers are in the same network and can talk to each other (which is a common problem). Docker provides so called allowing automatic service discovery. That basically means, that our nginx container can use the name of the php-fpm container to connect to it. Otherwise we would have to figure out the containers IP address in the default network every time we start the containers. 9reveals a list of the current networks 0Now let's add a new one called 91 for our web stack via 1 2Start the nginx container and connect it to the new network via 3Finally, we need to mount the local code folder 92 we mounted to the nginx container at 67 also in the php-fpm container in the same location: 4Note that we specified the network in the run command via the 94 option. We can verify that both containers are connected to the 91 by running 5 6The "Containers" key reveals that the 96 container has the IP address 172.18.0.3 and the docker-nginx container is reachable via 172.18.0.2. But can we actually connect from nginx to php-fpm? Let's find out:Log into the nginx container 7and ping the IP 8 9.. well, after we make the command available by installing 97: 00 01We can ping the container - that's good. But we were also promised we could reach the container by its name 96: 02 03And we can - awesome! Now we need to tell nginx to pass all PHP related requests to php-fpm by changing the 70 file on our windows host to 04Note the 00 line that tells nginx how to reach our php-fpm service. Because we mounted the 01 folder, we just need to reload nginx: 3and open http://127.0.0.1:8080/hello-world.php on a browser on your host machine. Btw. there's also a good tutorial on geekyplatypus.com on how to Dockerise your PHP application with Nginx and PHP7-FPM. But since it's using docker-compose you might want to read the next chapter first :) Putting it all together: Meet docker-composeLets sum up what we have do now to get everything up and running: 1. start php-cli 2. start nginx 3. start php-fpm 06Hm. That's alright I guess... but it also feels like "a lot". Wouldn't it be much better to have everything neatly defined in one place? I bet so! Let me introduce you to docker-compose
Lets do this step by step, starting with the php-cli container. Create the file 02: 07Before we get started, we're gonna clean up the old containers: 7To test the docker-compose.yml we need to run 03 from 04 09 10Note that the image is build from scratch when we run 05 for the first time. A 06 shows that the container is running fine, we can log in and execute source code from the host machine. 11Logging in 12and running 8works as before 14Now log out of the container and run 15to shut the container down again: 16Add the remaining services to the 07 file: 17And up again... 18 19Only nginx and php-fpm needed to be built because the php-cli one already existed. Lets check if we can still open http://127.0.0.1:8080/hello-world.php in a browser on the host machine: Yes we can! So instead of needing to run 3 different command with a bunch of parameters we're now down to 03. Looks like an improvement to me ;)The tl;drThe whole article is a lot to take in and it is most likely not the most efficient approach when you "just want to get started". So in this section we'll boil it down to only the necessary steps without in depth explanations.
Your application code lives in the 92 folder and changes are automatically available to the containers. This setup denotes the end of the first tutorial. In the next part we will learn how to set up Docker in PHPStorm, especially in combination with xdebug.Wrapping upCongratulations, you made it! If some things are not completely clear by now, don't hesitate to leave a comment. Apart from that, you should now have a first idea on what docker is and how you can use it. If you want to go deeper, please check out the remaining articles of the Docker PHP Tutorial series. Please subscribe to the RSS feed or to get automatic notifications when this next part comes out :) Wanna stay in touch?Since you ended up on this blog, chances are pretty high that you're into Software Development (probably PHP, Laravel, Docker or Google Big Query) and I'm a big fan of feedback and networking. So - if you'd like to stay in touch, feel free to shoot me an email with a couple of words about yourself and/or connect with me on LinkedIn or Twitter or simply subscribe to my RSS feed or go the crazy route and subscribe via mail and don't forget to leave a comment :) Subscribe to posts via mailEmail Address First Name We use Mailchimp as our newsletter provider. By clicking subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp's privacy practices here. |